├── .dockerignore ├── .github ├── dependabot.yml ├── mergify.yml └── workflows │ ├── chart-lint.yml │ ├── check-links.yml │ ├── ci.yml │ ├── dco.yml │ ├── deploy-manifest.yaml │ ├── docker-image.yml │ ├── main-latest.yml │ ├── mlc_config.json │ ├── release.yml │ ├── tool-docker-image.yml │ └── weekly.yml ├── .gitignore ├── .golangci.yml ├── Dockerfile ├── LICENSE ├── Makefile ├── OWNERS ├── PROJECT ├── README.md ├── apis └── milvus.io │ ├── v1alpha1 │ ├── components_types.go │ ├── dependencies_types.go │ ├── doc.go │ ├── groupversion_info.go │ ├── groupversion_info_test.go │ ├── milvus_types.go │ ├── milvus_webhook.go │ ├── milvuscluster_types.go │ ├── persistence_types.go │ ├── values_types.go │ ├── values_types_test.go │ └── zz_generated.deepcopy.go │ └── v1beta1 │ ├── components_types.go │ ├── dependencies_types.go │ ├── dependencies_types_test.go │ ├── doc.go │ ├── groupversion_info.go │ ├── groupversion_info_test.go │ ├── label_annotations.go │ ├── label_annotations_test.go │ ├── milvus_types.go │ ├── milvus_types_test.go │ ├── milvus_webhook.go │ ├── milvus_webhook_test.go │ ├── milvusupgrade_types.go │ ├── milvusupgrade_types_test.go │ ├── milvusupgrade_webhook.go │ ├── milvusupgrade_webhook_test.go │ ├── persistence_types.go │ ├── values_types.go │ ├── values_types_test.go │ └── zz_generated.deepcopy.go ├── charts └── milvus-operator │ ├── .helmignore │ ├── Chart.lock │ ├── Chart.yaml │ ├── charts │ └── cert-manager-v1.5.3.tgz │ ├── ci │ └── default-values.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── certificate.yaml │ ├── clusterrole.yaml │ ├── clusterrolebinding.yaml │ ├── crds.yaml │ ├── deployment.yaml │ ├── mutatingwebhookconfiguration.yaml │ ├── role.yaml │ ├── rolebinding.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ ├── servicemonitor.yaml │ └── validatingwebhookconfiguration.yaml │ └── values.yaml ├── codecov.yaml ├── config ├── assets │ └── templates │ │ ├── migration.yaml.tmpl │ │ ├── milvus-cluster.yaml.tmpl │ │ └── milvus.yaml.tmpl ├── cert │ └── csr.conf ├── crd │ ├── bases │ │ ├── milvus.io_milvusclusters.yaml │ │ ├── milvus.io_milvuses.yaml │ │ └── milvus.io_milvusupgrades.yaml │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── patches │ │ ├── cainjection_in_milvuses.yaml │ │ ├── cainjection_in_milvusupgrades.yaml │ │ ├── webhook_in_milvuses.yaml │ │ └── webhook_in_milvusupgrades.yaml ├── default │ ├── kustomization.yaml │ ├── manager_auth_proxy_patch.yaml │ ├── manager_config_patch.yaml │ ├── manager_webhook_patch.yaml │ └── webhookcainjection_patch.yaml ├── dev │ ├── debug_service.yaml │ ├── kustomization.yaml │ ├── manager_dev_patch.yaml │ └── webhook_patch.yaml ├── helm │ ├── certificate │ │ ├── kustomization.yaml │ │ ├── patch_certificate_dns.yaml │ │ └── patch_certificate_secret.yaml │ ├── crds │ │ ├── kustomization.yaml │ │ └── webhook_patch.yaml │ ├── rbac │ │ ├── kustomization.yaml │ │ ├── patch_leaderelection_binding.yaml │ │ └── patch_manager_binding.yaml │ └── webhook │ │ ├── kustomization.yaml │ │ ├── mutatingwebhook_endpoint_patch.yaml │ │ └── validatingwebhook_endpoint_patch.yaml ├── kind │ └── kind-dev.yaml ├── manager │ ├── controller_manager_config.yaml │ ├── kustomization.yaml │ └── namespace.yaml ├── prometheus │ ├── kustomization.yaml │ └── monitor.yaml ├── rbac │ ├── auth_proxy_client_clusterrole.yaml │ ├── auth_proxy_role.yaml │ ├── auth_proxy_role_binding.yaml │ ├── auth_proxy_service.yaml │ ├── kustomization.yaml │ ├── leader_election_role.yaml │ ├── leader_election_role_binding.yaml │ ├── milvus_editor_role.yaml │ ├── milvus_viewer_role.yaml │ ├── milvusupgrade_editor_role.yaml │ ├── milvusupgrade_viewer_role.yaml │ ├── role.yaml │ ├── role_binding.yaml │ └── service_account.yaml ├── samples │ ├── beta │ │ ├── README.md │ │ ├── milvus_streaming_node.yaml │ │ └── milvus_woodpecker.yaml │ ├── cluster_demo.yaml │ ├── demo.yaml │ ├── external_tls.yaml │ ├── hpa.yaml │ ├── internal_tls.yaml │ ├── milvus_azure_blob_accesskey.yaml │ ├── milvus_azure_blob_connection_string.yaml │ ├── milvus_azure_blob_iam.yaml │ ├── milvus_cluster_4coords.yaml │ ├── milvus_cluster_default.yaml │ ├── milvus_cluster_minimum.yaml │ ├── milvus_cluster_mixcoord.yaml │ ├── milvus_cluster_resource.yaml │ ├── milvus_config.yaml │ ├── milvus_config_dynamic.yaml │ ├── milvus_default.yaml │ ├── milvus_deletion.yaml │ ├── milvus_etcd_auth.yaml │ ├── milvus_external_dependencies.yaml │ ├── milvus_external_minio_ssl.yaml │ ├── milvus_gcs.yaml │ ├── milvus_gcs_iam.yaml │ ├── milvus_kafka.yaml │ ├── milvus_metric_labels.yaml │ ├── milvus_minimum.yaml │ ├── milvus_natsmq.yaml │ ├── milvus_pulsar_v2.yaml │ ├── milvus_pulsar_with_authn_jwt_token.yaml │ ├── milvus_resource.yaml │ ├── milvus_rocksmq.yaml │ ├── milvus_rolling_update.yaml │ ├── milvus_s3.yaml │ ├── milvus_s3_iam.yaml │ ├── milvusupgrade.yaml │ └── run_as_non_root.yaml └── webhook │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── manifests.yaml │ └── service.yaml ├── ct.yaml ├── deploy └── manifests │ └── deployment.yaml ├── docs ├── CRD │ ├── (deprecated)milvus-cluster.md │ └── milvus.md ├── administration │ ├── allocate-resources.md │ ├── configure-milvus.md │ ├── manage-dependencies │ │ ├── message-storage.md │ │ ├── meta-storage.md │ │ └── object-storage.md │ ├── monitor-and-alert.md │ ├── scale-a-milvus-cluster.md │ ├── security │ │ ├── enable-authentication.md │ │ └── encryption-in-transit.md │ └── upgrade.md ├── arch │ ├── arch.md │ └── reconcile.md ├── images │ └── arch.jpg └── installation │ ├── installation.md │ └── kind-installation.md ├── go.mod ├── go.sum ├── hack ├── boilerplate.go.txt ├── generate-groups.sh └── update-codegen.sh ├── local.Dockerfile ├── main.go ├── pkg ├── client │ ├── clientset │ │ └── versioned │ │ │ ├── clientset.go │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── clientset_generated.go │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ ├── scheme │ │ │ ├── doc.go │ │ │ └── register.go │ │ │ └── typed │ │ │ └── milvus.io │ │ │ └── v1beta1 │ │ │ ├── doc.go │ │ │ ├── fake │ │ │ ├── doc.go │ │ │ ├── fake_milvus.go │ │ │ └── fake_milvus.io_client.go │ │ │ ├── generated_expansion.go │ │ │ ├── milvus.go │ │ │ └── milvus.io_client.go │ ├── informers │ │ └── externalversions │ │ │ ├── factory.go │ │ │ ├── generic.go │ │ │ ├── internalinterfaces │ │ │ └── factory_interfaces.go │ │ │ └── milvus.io │ │ │ ├── interface.go │ │ │ └── v1beta1 │ │ │ ├── interface.go │ │ │ └── milvus.go │ └── listers │ │ └── milvus.io │ │ └── v1beta1 │ │ ├── expansion_generated.go │ │ └── milvus.go ├── config │ ├── config.go │ └── config_test.go ├── controllers │ ├── common_test.go │ ├── component_condition.go │ ├── component_condition_test.go │ ├── components.go │ ├── components_test.go │ ├── conditions.go │ ├── conditions_test.go │ ├── configmaps.go │ ├── configmaps_test.go │ ├── dependencies.go │ ├── dependencies_test.go │ ├── dependency_graph.go │ ├── deploy_ctrl.go │ ├── deploy_ctrl_factory.go │ ├── deploy_ctrl_test.go │ ├── deploy_ctrl_util.go │ ├── deploy_ctrl_util_test.go │ ├── deploy_mode_changer.go │ ├── deploy_mode_changer_test.go │ ├── deployment_updater.go │ ├── deployment_updater_test.go │ ├── deployments.go │ ├── deployments_test.go │ ├── endpoint_check_cache.go │ ├── endpoint_check_cache_test.go │ ├── error_detail.go │ ├── error_detail_test.go │ ├── external_interfaces.go │ ├── group_runner.go │ ├── group_runner_test.go │ ├── groups.go │ ├── groups_test.go │ ├── ingress.go │ ├── ingress_test.go │ ├── k8s_default_values.go │ ├── manager_interface.go │ ├── metrics.go │ ├── milvus.go │ ├── milvus_controller.go │ ├── milvus_controller_test.go │ ├── milvus_test.go │ ├── milvuscluster │ │ └── convert_controller.go │ ├── milvusupgrade_controller.go │ ├── milvusupgrade_controller_test.go │ ├── milvusupgrade_fsm.go │ ├── milvusupgrade_fsm_test.go │ ├── podmonitor.go │ ├── podmonitor_test.go │ ├── pvc.go │ ├── pvc_test.go │ ├── rolling_mode_status_updater.go │ ├── rolling_mode_status_updater_test.go │ ├── rollout_util.go │ ├── rollout_util_test.go │ ├── services.go │ ├── services_test.go │ ├── setup.go │ ├── status_cluster.go │ ├── status_cluster_test.go │ ├── utils.go │ └── utils_test.go ├── external │ ├── iam │ │ ├── aliyun.go │ │ ├── aws.go │ │ ├── azure.go │ │ ├── gcp.go │ │ └── tencent.go │ ├── kafka.go │ ├── kafka_test.go │ ├── minio.go │ ├── minio_test.go │ ├── pulsar.go │ ├── pulsar_client.go │ ├── pulsar_test.go │ └── tcp_dial.go ├── helm │ ├── helm.go │ ├── interface.go │ └── values │ │ ├── testing.go │ │ └── values.go ├── manager │ └── manager.go └── util │ ├── diff.go │ ├── diff_test.go │ ├── k8s_client.go │ ├── k8s_client_test.go │ ├── rest │ ├── rest_client.go │ └── rest_client_test.go │ ├── testing.go │ ├── testing_test.go │ ├── util.go │ ├── util_test.go │ └── yamlparser │ ├── file.go │ └── file_test.go ├── scripts ├── bump-version.sh ├── debug.sh ├── init.sh ├── run-helm.sh └── run.sh ├── test ├── after-upgrade.py ├── batch-create │ └── main.go ├── batch-delete │ └── main.go ├── before-upgrade.py ├── hello-milvus-job.yaml ├── hello-milvus.py ├── milvus-2.4.yaml ├── milvus-upgrade.sh ├── min-mc-alpha.yaml ├── min-mc-feature.yaml ├── min-mc-kafka.yaml ├── min-mc-mixture.yaml ├── min-mc.yaml ├── min-milvus-alpha.yaml ├── min-milvus-feature.yaml ├── min-milvus-kafka.yaml ├── min-milvus.yaml ├── patch-2.5.yaml ├── sit.sh ├── upgrade.sh ├── user.yaml └── values.yaml ├── tool.Dockerfile └── tool ├── cp └── main.go ├── iam-verify └── main.go └── merge └── main.go /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | -------------------------------------------------------------------------------- /.github/mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: remove hold when CI passed or documentation 3 | conditions: 4 | - or: 5 | - label=ci-passed 6 | - label=documentation 7 | actions: 8 | label: 9 | remove: 10 | - do-not-merge/hold 11 | - name: add hold when CI not passed or documentation 12 | conditions: 13 | - label!=ci-passed 14 | - label!=documentation 15 | actions: 16 | label: 17 | add: 18 | - do-not-merge/hold 19 | - name: remove ci-pass when CI not passed 20 | conditions: 21 | - or: 22 | - check-success!=check 23 | - check-success!=Code Check (ubuntu24.04) 24 | - check-success!=Unit Test (ubuntu24.04) 25 | - check-success!=System Integration Test (ubuntu24.04) 26 | - check-success!=System Integration Test for Mixture (ubuntu24.04) 27 | - check-success!=System Integration Test for Upgrade (ubuntu24.04) 28 | - check-success!=System Integration Test for New Feature (ubuntu24.04) 29 | - check-success!=System Integration Test for Milvus Upgrade (ubuntu24.04) 30 | - check-success!=Test Deploy by Manifest (ubuntu24.04) 31 | - check-success!=codecov/patch 32 | - check-success!=codecov/project 33 | actions: 34 | label: 35 | remove: 36 | - ci-passed 37 | - name: add ci-pass when CI passed 38 | conditions: 39 | - check-success=check 40 | - check-success=Code Check (ubuntu24.04) 41 | - check-success=Unit Test (ubuntu24.04) 42 | - check-success=System Integration Test (ubuntu24.04) 43 | - check-success=System Integration Test for Mixture (ubuntu24.04) 44 | - check-success=System Integration Test for Upgrade (ubuntu24.04) 45 | - check-success=System Integration Test for New Feature (ubuntu24.04) 46 | - check-success=System Integration Test for Milvus Upgrade (ubuntu24.04) 47 | - check-success=Test Deploy by Manifest (ubuntu24.04) 48 | - check-success=codecov/patch 49 | - check-success=codecov/project 50 | actions: 51 | label: 52 | add: 53 | - ci-passed 54 | -------------------------------------------------------------------------------- /.github/workflows/chart-lint.yml: -------------------------------------------------------------------------------- 1 | name: Chart Lint Test 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'charts/**' 7 | 8 | jobs: 9 | chart-lint-test: 10 | name: Chart Lint Test 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | with: 16 | submodules: recursive 17 | - name: Set up Helm 18 | uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 19 | with: 20 | version: v3.4.0 21 | - name: Add dependency chart repos 22 | run: | 23 | helm repo add cert-manager https://charts.jetstack.io 24 | 25 | - name: Set up chart-testing 26 | uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0 27 | 28 | - name: Run chart-testing (lint) 29 | run: ct lint --all --config ct.yaml 30 | 31 | - name: Create KinD cluster 32 | uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0 33 | 34 | - name: Run chart-testing (install) 35 | id: install 36 | run: ct install --all --config ct.yaml 37 | -------------------------------------------------------------------------------- /.github/workflows/check-links.yml: -------------------------------------------------------------------------------- 1 | name: Markdown Links Check 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - '**.md' 9 | pull_request: 10 | paths: 11 | - '**.md' 12 | 13 | jobs: 14 | markdown-link-check: 15 | name: Broken Links 16 | runs-on: ubuntu-latest 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 20 | with: 21 | submodules: recursive 22 | - name: Run link check 23 | uses: gaurav-nelson/github-action-markdown-link-check@636e17b35a5803e014b7272d9e46a8262705416a # 1.0.16 24 | with: 25 | use-quiet-mode: 'no' 26 | use-verbose-mode: 'yes' 27 | config-file: '.github/workflows/mlc_config.json' 28 | -------------------------------------------------------------------------------- /.github/workflows/dco.yml: -------------------------------------------------------------------------------- 1 | name: DCO Check 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | check: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: tisonkun/actions-dco@6d1f8a197db1b04df1769707b46b9366b1eca902 # v1.1 10 | -------------------------------------------------------------------------------- /.github/workflows/deploy-manifest.yaml: -------------------------------------------------------------------------------- 1 | name: Test Deploy With Minifest 2 | 3 | # This workflow is triggered on any golang code, makefile, workflow changes to repository. 4 | on: 5 | push: 6 | paths-ignore: 7 | - 'docs/**' 8 | pull_request: 9 | paths-ignore: 10 | - 'docs/**' 11 | 12 | jobs: 13 | deploy-by-manifest: 14 | name: Test Deploy by Manifest 15 | runs-on: ubuntu-latest 16 | timeout-minutes: 40 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | os: [ubuntu24.04] 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | - name: Setup KinD Cluster 25 | uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0 26 | with: 27 | cluster_name: kind 28 | - name: Deploy by manifest 29 | run: | 30 | make deploy-by-manifest 31 | - name: Test Webhook 32 | run : | 33 | set -ex 34 | kubectl create -f ./config/samples/milvus_minimum.yaml 35 | kubectl delete -f ./config/samples/milvus_minimum.yaml 36 | kubectl create -f ./config/samples/milvus_cluster_minimum.yaml 37 | kubectl delete -f ./config/samples/milvus_cluster_minimum.yaml 38 | -------------------------------------------------------------------------------- /.github/workflows/main-latest.yml: -------------------------------------------------------------------------------- 1 | name: Build and Push Latest on Main 2 | 3 | # This workflow is triggered on new pushed to the main branch. 4 | on: 5 | push: 6 | branches: 7 | - main 8 | 9 | jobs: 10 | publish-builder: 11 | name: Publish Builder 12 | runs-on: ubuntu-latest 13 | timeout-minutes: 15 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | os: [ubuntu24.04] 18 | env: 19 | OS_NAME: ${{ matrix.os }} 20 | REGISTRY_NAME: milvusdb/milvus-operator 21 | IMAGE_TAG: "main-latest" 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | - name: Build Docker Image 26 | shell: bash 27 | run: | 28 | docker build -t ${REGISTRY_NAME}:${IMAGE_TAG} . 29 | - name: Push Docker Image 30 | shell: bash 31 | run: | 32 | docker login -u ${{ secrets.MILVUSDB_DOCKER_USER }} \ 33 | -p ${{ secrets.MILVUSDB_DOCKER_PWD }} 34 | docker push ${REGISTRY_NAME}:${IMAGE_TAG} 35 | -------------------------------------------------------------------------------- /.github/workflows/mlc_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "retryOn429": true, 3 | "retryCount": 5, 4 | "fallbackRetryDelay": "30s" 5 | } -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | # This workflow is triggered on pushes or pull request to the repository. 4 | on: 5 | push: 6 | tags: 7 | - "*" 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 15 | with: 16 | fetch-depth: 0 17 | 18 | - name: Configure Git 19 | run: | 20 | git config user.name "$GITHUB_ACTOR" 21 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 22 | 23 | - name: Set up Helm 24 | uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4.3.0 25 | with: 26 | version: v3.4.0 27 | - name: Add dependency chart repos 28 | run: | 29 | helm repo add cert-manager https://charts.jetstack.io 30 | 31 | - name: Set up chart-testing 32 | uses: helm/chart-testing-action@0d28d3144d3a25ea2cc349d6e59901c4ff469b3b # v2.7.0 33 | 34 | - name: Run chart-testing (lint) 35 | run: ct lint --all --config ct.yaml 36 | 37 | - name: Run chart-releaser 38 | uses: helm/chart-releaser-action@a0d2dc62c5e491af8ef6ba64a2e02bcf3fb33aa1 # v1.7.0 39 | env: 40 | CR_TOKEN: "${{ secrets.CR_TOKEN }}" 41 | -------------------------------------------------------------------------------- /.github/workflows/weekly.yml: -------------------------------------------------------------------------------- 1 | name: Weekly Test 2 | on: 3 | schedule: 4 | # * is a special character in YAML so you have to quote this string 5 | # ┌───────────── minute (0 - 59) 6 | # │ ┌───────────── hour (0 - 23) 7 | # │ │ ┌───────────── day of the month (1 - 31) 8 | # │ │ │ ┌───────────── month (1 - 12 or JAN-DEC) 9 | # │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT) 10 | # │ │ │ │ │ 11 | # │ │ │ │ │ 12 | # │ │ │ │ │ 13 | - cron: '0 23 * * 0' 14 | 15 | jobs: 16 | weekly-alpha: 17 | name: System Integration Test for v1alpha1 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 40 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | os: [ubuntu24.04] 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 27 | - name: Prepare Docker Images 28 | run: | 29 | make sit-prepare-images 30 | - name: Setup KinD Cluster 31 | uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0 32 | with: 33 | cluster_name: kind 34 | - name: Deploy to KinD 35 | run: | 36 | make sit-deploy 37 | - name: Integration Test 38 | run: | 39 | make sit-test test_mode=alpha 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | tmp 11 | config/dev/webhook_patch_ca.yaml 12 | 13 | # Test binary, build with `go test -c` 14 | *.test 15 | 16 | # Output of the go coverage tool, specifically when used with LiteIDE 17 | *.out 18 | 19 | # Kubernetes Generated files - skip generated files, except for vendored files 20 | 21 | !vendor/**/zz_generated.* 22 | 23 | # editor and IDE paraphernalia 24 | .idea 25 | *.swp 26 | *.swo 27 | *~ 28 | .vscode 29 | 30 | __debug_bin 31 | *.DS_Store 32 | 33 | ## goreleaser 34 | dist/ 35 | vendor/ 36 | 37 | ## generated 38 | test/*_gen.yaml 39 | *_mock.go 40 | 41 | # Helm packages 42 | charts/index.yaml 43 | charts/*.tgz 44 | 45 | # output 46 | out/ 47 | *.bak 48 | 49 | .gocache/ 50 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | formatters: 3 | enable: 4 | - goimports 5 | settings: 6 | goimports: 7 | local-prefixes: 8 | - github.com/zilliztech/milvus-operator 9 | linters: 10 | enable: 11 | - gocritic 12 | - misspell 13 | - revive 14 | exclusions: 15 | rules: 16 | - linters: 17 | - errcheck 18 | # Taken from the default exclusions in v1. 19 | text: Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv). is not checked 20 | - linters: 21 | - errcheck 22 | path: _test.go 23 | settings: 24 | revive: 25 | rules: 26 | # Disable checks for package and exported functions/vars. There are many to fix still. 27 | - name: package-comments 28 | disabled: true 29 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.24 as builder 2 | 3 | WORKDIR /workspace 4 | # ENV GOPROXY https://goproxy.cn 5 | # Copy the Go Modules manifests 6 | # # cache deps before building and copying source so that we don't need to re-download as much 7 | # # and so that source changes don't invalidate our downloaded layer 8 | # 9 | # # Copy the go source 10 | COPY go.mod go.mod 11 | COPY go.sum go.sum 12 | RUN go mod download 13 | # 14 | # # Build 15 | COPY main.go main.go 16 | COPY apis/ apis/ 17 | COPY pkg/ pkg/ 18 | COPY tool/ tool/ 19 | COPY config/assets out/config/assets 20 | COPY scripts/ scripts/ 21 | COPY Makefile Makefile 22 | RUN make docker-prepare 23 | # 24 | # # Use distroless as minimal base image to package the manager binary 25 | # # Refer to https://github.com/GoogleContainerTools/distroless for more details 26 | FROM alpine:3.21 27 | WORKDIR / 28 | COPY --from=builder /workspace/out/ / 29 | 30 | USER 65532:65532 31 | 32 | ENTRYPOINT ["/manager"] 33 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | filters: 2 | ".*": 3 | approvers: 4 | - zwd1208 5 | - haorenfsa 6 | - loveeachday 7 | - AlintaLu 8 | - yellow-shine 9 | reviewers: 10 | - zwd1208 11 | - haorenfsa 12 | - loveeachday 13 | - AlintaLu 14 | - yellow-shine 15 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | domain: milvus.io 2 | layout: 3 | - go.kubebuilder.io/v3 4 | multigroup: true 5 | projectName: milvus-operator 6 | repo: github.com/zilliztech/milvus-operator 7 | resources: 8 | # TODO: deprecated 9 | - api: 10 | crdVersion: v1 11 | namespaced: true 12 | controller: true 13 | domain: milvus.io 14 | kind: MilvusCluster 15 | path: github.com/zilliztech/milvus-operator/apis/milvus.io/v1alpha1 16 | version: v1alpha1 17 | webhooks: 18 | defaulting: true 19 | validation: true 20 | webhookVersion: v1 21 | - api: 22 | crdVersion: v1 23 | namespaced: true 24 | controller: true 25 | domain: milvus.io 26 | kind: Milvus 27 | path: github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1 28 | version: v1beta1 29 | webhooks: 30 | defaulting: true 31 | validation: true 32 | webhookVersion: v1 33 | - api: 34 | crdVersion: v1 35 | namespaced: true 36 | controller: true 37 | domain: milvus.io 38 | kind: MilvusUpgrade 39 | path: github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1 40 | version: v1beta1 41 | version: "3" 42 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=milvus.io 19 | 20 | package v1alpha1 21 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains API Schema definitions for the v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=milvus.io 20 | package v1alpha1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "milvus.io", Version: "v1alpha1"} 30 | 31 | // for code-generator 32 | SchemeGroupVersion = GroupVersion 33 | 34 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 35 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 36 | 37 | // AddToScheme adds the types in this group-version to the given scheme. 38 | AddToScheme = SchemeBuilder.AddToScheme 39 | ) 40 | 41 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 42 | func Resource(resource string) schema.GroupResource { 43 | return GroupVersion.WithResource(resource).GroupResource() 44 | } 45 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/groupversion_info_test.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestResource(t *testing.T) { 10 | ret := Resource("test") 11 | assert.Equal(t, "milvus.io", ret.Group) 12 | assert.Equal(t, "test", ret.Resource) 13 | } 14 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/persistence_types.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import corev1 "k8s.io/api/core/v1" 4 | 5 | // Persistence is persistence for milvus 6 | type Persistence struct { 7 | // If Enabled, will create/use pvc for data persistence 8 | // +kubebuilder:validation:Optional 9 | Enabled bool `json:"enabled,omitempty"` 10 | // +kubebuilder:validation:Optional 11 | // +kubebuilder:default:="/var/lib/milvus" 12 | MountPath string `json:"mountPath,omitempty"` 13 | // +kubebuilder:validation:Optional 14 | PVCDeletion bool `json:"pvcDeletion,omitempty"` 15 | // +kubebuilder:validation:Optional 16 | PersistentVolumeClaim PersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` 17 | } 18 | 19 | // PersistentVolumeClaim for milvus 20 | type PersistentVolumeClaim struct { 21 | // ExistingClaim if not empty, will use existing pvc, else create a pvc 22 | // +kubebuilder:validation:Optional 23 | ExistingClaim string `json:"existingClaim,omitempty"` 24 | 25 | // Map of string keys and values that can be used to organize and categorize 26 | // (scope and select) objects. May match selectors of replication controllers 27 | // and services. 28 | // More info: http://kubernetes.io/docs/user-guide/labels 29 | // +optional 30 | Labels map[string]string `json:"labels,omitempty"` 31 | 32 | // Annotations is an unstructured key value map stored with a resource that may be 33 | // set by external tools to store and retrieve arbitrary metadata. They are not 34 | // queryable and should be preserved when modifying objects. 35 | // More info: http://kubernetes.io/docs/user-guide/annotations 36 | // +optional 37 | Annotations map[string]string `json:"annotations,omitempty"` 38 | 39 | // Spec defines the desired characteristics of a volume requested by a pod author. 40 | // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims 41 | // +kubebuilder:validation:Optional 42 | Spec corev1.PersistentVolumeClaimSpec `json:"spec,omitempty"` 43 | } 44 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/values_types.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import "encoding/json" 4 | 5 | type Values struct { 6 | // Work around for https://github.com/kubernetes-sigs/kubebuilder/issues/528 7 | Data map[string]interface{} `json:"-"` 8 | } 9 | 10 | func (v Values) MarshalJSON() ([]byte, error) { 11 | return json.Marshal(v.Data) 12 | } 13 | 14 | func (v *Values) UnmarshalJSON(data []byte) error { 15 | var out map[string]interface{} 16 | 17 | err := json.Unmarshal(data, &out) 18 | if err != nil { 19 | return err 20 | } 21 | 22 | v.Data = out 23 | 24 | return nil 25 | } 26 | 27 | // DeepCopyInto is an deepcopy function, copying the receiver, writing 28 | // into out. In must be non-nil. Declaring this here prevents it from 29 | // being generated in `zz_generated.deepcopy.go`. 30 | // 31 | // This exists here to work around https://github.com/kubernetes/code-generator/issues/50, 32 | // and partially around https://github.com/kubernetes-sigs/controller-tools/pull/126 33 | // and https://github.com/kubernetes-sigs/controller-tools/issues/294. 34 | func (v *Values) DeepCopyInto(out *Values) { 35 | b, err := json.Marshal(v.Data) 36 | if err != nil { 37 | // The marshal should have been performed cleanly as otherwise 38 | // the resource would not have been created by the API server. 39 | panic(err) 40 | } 41 | 42 | var c map[string]interface{} 43 | 44 | err = json.Unmarshal(b, &c) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | out.Data = c 50 | } 51 | -------------------------------------------------------------------------------- /apis/milvus.io/v1alpha1/values_types_test.go: -------------------------------------------------------------------------------- 1 | package v1alpha1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestValues_MarshalUnmarshalJSON(t *testing.T) { 10 | values := Values{ 11 | Data: map[string]interface{}{ 12 | "key": "value", 13 | }, 14 | } 15 | 16 | expected := `{"key":"value"}` 17 | actual, err := values.MarshalJSON() 18 | if err != nil { 19 | t.Errorf("unexpected error: %v", err) 20 | } 21 | assert.Equal(t, expected, string(actual)) 22 | 23 | var values2 Values 24 | err = values2.UnmarshalJSON(actual) 25 | if err != nil { 26 | t.Errorf("unexpected error: %v", err) 27 | } 28 | assert.Equal(t, values, values2) 29 | } 30 | func TestValues_DeepCopyInfo(t *testing.T) { 31 | values := &Values{ 32 | Data: map[string]interface{}{ 33 | "key": "value", 34 | }, 35 | } 36 | values2 := &Values{} 37 | values.DeepCopyInto(values2) 38 | assert.NotSame(t, values, values2) 39 | assert.NotSame(t, &values.Data, &values2.Data) 40 | assert.Equal(t, values, values2) 41 | } 42 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/dependencies_types_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestMilvusDependencies_GetMilvusBuiltInMQ(t *testing.T) { 10 | m := &MilvusDependencies{ 11 | MsgStreamType: MsgStreamTypePulsar, 12 | } 13 | assert.Nil(t, m.GetMilvusBuiltInMQ()) 14 | m.MsgStreamType = MsgStreamTypeKafka 15 | assert.Nil(t, m.GetMilvusBuiltInMQ()) 16 | 17 | m.MsgStreamType = MsgStreamTypeCustom 18 | assert.Nil(t, m.GetMilvusBuiltInMQ()) 19 | 20 | m.MsgStreamType = MsgStreamType("unknown") 21 | assert.Nil(t, m.GetMilvusBuiltInMQ()) 22 | 23 | m.MsgStreamType = MsgStreamTypeWoodPecker 24 | assert.NotNil(t, m.GetMilvusBuiltInMQ()) 25 | assert.Equal(t, &m.WoodPecker, m.GetMilvusBuiltInMQ()) 26 | 27 | m.MsgStreamType = MsgStreamTypeRocksMQ 28 | assert.NotNil(t, m.GetMilvusBuiltInMQ()) 29 | assert.Equal(t, &m.RocksMQ, m.GetMilvusBuiltInMQ()) 30 | 31 | m.MsgStreamType = MsgStreamTypeNatsMQ 32 | assert.NotNil(t, m.GetMilvusBuiltInMQ()) 33 | assert.Equal(t, &m.NatsMQ, m.GetMilvusBuiltInMQ()) 34 | } 35 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // +k8s:deepcopy-gen=package 18 | // +groupName=milvus.io 19 | 20 | package v1beta1 21 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // package v1beta1 contains API Schema definitions for the v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=milvus.io 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "milvus.io", Version: "v1beta1"} 30 | 31 | // for code-generator 32 | SchemeGroupVersion = GroupVersion 33 | 34 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 35 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 36 | 37 | // AddToScheme adds the types in this group-version to the given scheme. 38 | AddToScheme = SchemeBuilder.AddToScheme 39 | ) 40 | 41 | // Resource takes an unqualified resource and returns a Group qualified GroupResource 42 | func Resource(resource string) schema.GroupResource { 43 | return GroupVersion.WithResource(resource).GroupResource() 44 | } 45 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/groupversion_info_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestResource(t *testing.T) { 10 | ret := Resource("test") 11 | assert.Equal(t, "milvus.io", ret.Group) 12 | assert.Equal(t, "test", ret.Resource) 13 | } 14 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/label_annotations_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestLabelsImpl_IsChangeQueryNodeMode_SetChangingQueryNodeMode(t *testing.T) { 10 | mc := Milvus{} 11 | mc.Default() 12 | assert.False(t, Labels().IsChangingMode(mc, DataNodeName)) 13 | Labels().SetChangingMode(&mc, DataNodeName, true) 14 | assert.True(t, Labels().IsChangingMode(mc, DataNodeName)) 15 | Labels().SetChangingMode(&mc, DataNodeName, false) 16 | assert.False(t, Labels().IsChangingMode(mc, DataNodeName)) 17 | } 18 | 19 | func TestLabelsImpl_GetLabelQueryNodeGroupID_SetQueryNodeGroupID(t *testing.T) { 20 | mc := Milvus{} 21 | mc.Default() 22 | assert.Equal(t, "", Labels().GetLabelGroupID(DataNodeName, &mc)) 23 | Labels().SetGroupID(DataNodeName, mc.Labels, 1) 24 | assert.Equal(t, "1", Labels().GetLabelGroupID(DataNodeName, &mc)) 25 | Labels().SetGroupID(DataNodeName, mc.Labels, 0) 26 | assert.Equal(t, "0", Labels().GetLabelGroupID(DataNodeName, &mc)) 27 | 28 | } 29 | 30 | func TestLabelsImpl_GetCurrentQueryNodeGroupId_SetCurrentQueryNodeGroupID(t *testing.T) { 31 | mc := Milvus{} 32 | mc.Default() 33 | assert.Equal(t, "", Labels().GetCurrentGroupId(&mc, DataNodeName)) 34 | Labels().SetCurrentGroupID(&mc, DataNodeName, 1) 35 | assert.Equal(t, "1", Labels().GetCurrentGroupId(&mc, DataNodeName)) 36 | Labels().SetCurrentGroupID(&mc, DataNodeName, 0) 37 | assert.Equal(t, "0", Labels().GetCurrentGroupId(&mc, DataNodeName)) 38 | } 39 | 40 | func TestLabelsImpl_IsQueryNodeRolling_GetQueryNodeRollingId_SetQueryNodeRolling(t *testing.T) { 41 | mc := Milvus{} 42 | mc.Generation = 1 43 | mc.Default() 44 | assert.False(t, Labels().IsComponentRolling(mc, DataNodeName)) 45 | assert.Equal(t, "", Labels().GetComponentRollingId(mc, DataNodeName)) 46 | Labels().SetComponentRolling(&mc, DataNodeName, true) 47 | assert.True(t, Labels().IsComponentRolling(mc, DataNodeName)) 48 | assert.Equal(t, "1", Labels().GetComponentRollingId(mc, DataNodeName)) 49 | Labels().SetComponentRolling(&mc, DataNodeName, false) 50 | assert.False(t, Labels().IsComponentRolling(mc, DataNodeName)) 51 | assert.Equal(t, "", Labels().GetComponentRollingId(mc, DataNodeName)) 52 | } 53 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/milvusupgrade_types_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestObjectReference_Object(t *testing.T) { 10 | s := new(ObjectReference) 11 | obj := s.Object() 12 | assert.Equal(t, s.Namespace, obj.Namespace) 13 | assert.Equal(t, s.Name, obj.Name) 14 | } 15 | 16 | func TestMilvusUpgradeState_NeedRequeue(t *testing.T) { 17 | s := UpgradeStateSucceeded 18 | assert.False(t, s.NeedRequeue()) 19 | s = UpgradeStatePending 20 | assert.True(t, s.NeedRequeue()) 21 | s = UpgradeStateOldVersionStopping 22 | assert.True(t, s.NeedRequeue()) 23 | } 24 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/milvusupgrade_webhook_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestMilvusUpgrade_Default(t *testing.T) { 10 | r := new(MilvusUpgrade) 11 | r.Spec.TargetVersion = "2.2.0" 12 | r.Default() 13 | assert.Equal(t, "milvusdb/milvus:v2.2.0", r.Spec.TargetImage) 14 | assert.Equal(t, defaultToolImage, r.Spec.ToolImage) 15 | 16 | r.Spec.TargetVersion = "v2.2.0" 17 | r.Default() 18 | assert.Equal(t, "milvusdb/milvus:v2.2.0", r.Spec.TargetImage) 19 | } 20 | 21 | func TestMilvusUpgrade_Validate(t *testing.T) { 22 | r := new(MilvusUpgrade) 23 | assert.Error(t, r.Validate()) 24 | 25 | t.Run("not support source versions", func(t *testing.T) { 26 | r.Spec.SourceVersion = "1.0" 27 | r.Spec.TargetVersion = "2.2.0" 28 | assert.Error(t, r.Validate()) 29 | 30 | r.Spec.SourceVersion = "2.0.0-rc1" 31 | r.Spec.TargetVersion = "2.2.0" 32 | assert.Error(t, r.Validate()) 33 | }) 34 | 35 | t.Run("not support target versions", func(t *testing.T) { 36 | r.Spec.SourceVersion = "2.1.0" 37 | r.Spec.TargetVersion = "2.0.0" 38 | assert.Error(t, r.Validate()) 39 | }) 40 | 41 | t.Run("ok", func(t *testing.T) { 42 | r.Spec.SourceVersion = "v2.0.0" 43 | r.Spec.TargetVersion = "v2.2.0" 44 | assert.NoError(t, r.Validate()) 45 | 46 | r.Spec.SourceVersion = "2.1.4" 47 | r.Spec.TargetVersion = "2.2.0" 48 | assert.NoError(t, r.Validate()) 49 | _, err := r.ValidateCreate() 50 | assert.NoError(t, err) 51 | _, err = r.ValidateUpdate(r) 52 | assert.NoError(t, err) 53 | _, err = r.ValidateDelete() 54 | assert.NoError(t, err) 55 | }) 56 | } 57 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/persistence_types.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import corev1 "k8s.io/api/core/v1" 4 | 5 | const RocksMQPersistPath = "/var/lib/milvus" 6 | 7 | // Persistence is persistence for milvus 8 | type Persistence struct { 9 | // If Enabled, will create/use pvc for data persistence 10 | // +kubebuilder:validation:Optional 11 | Enabled bool `json:"enabled,omitempty"` 12 | // +kubebuilder:validation:Optional 13 | PVCDeletion bool `json:"pvcDeletion,omitempty"` 14 | // +kubebuilder:validation:Optional 15 | PersistentVolumeClaim PersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"` 16 | } 17 | 18 | // PersistentVolumeClaim for milvus 19 | type PersistentVolumeClaim struct { 20 | // ExistingClaim if not empty, will use existing pvc, else create a pvc 21 | // +kubebuilder:validation:Optional 22 | ExistingClaim string `json:"existingClaim,omitempty"` 23 | 24 | // Map of string keys and values that can be used to organize and categorize 25 | // (scope and select) objects. May match selectors of replication controllers 26 | // and services. 27 | // More info: http://kubernetes.io/docs/user-guide/labels 28 | // +optional 29 | Labels map[string]string `json:"labels,omitempty"` 30 | 31 | // Annotations is an unstructured key value map stored with a resource that may be 32 | // set by external tools to store and retrieve arbitrary metadata. They are not 33 | // queryable and should be preserved when modifying objects. 34 | // More info: http://kubernetes.io/docs/user-guide/annotations 35 | // +optional 36 | Annotations map[string]string `json:"annotations,omitempty"` 37 | 38 | // Spec defines the desired characteristics of a volume requested by a pod author. 39 | // It's same as corev1.PersistentVolumeClaimSpec, we use a Values here to avoid the CRD become too large 40 | // More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims 41 | // +optional 42 | // +nullable 43 | // +kubebuilder:pruning:PreserveUnknownFields 44 | Spec Values `json:"spec,omitempty"` 45 | } 46 | 47 | func (p *PersistentVolumeClaim) GetSpec() *corev1.PersistentVolumeClaimSpec { 48 | ret := new(corev1.PersistentVolumeClaimSpec) 49 | p.Spec.AsObject(ret) //nolint:errcheck 50 | return ret 51 | } 52 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/values_types.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "reflect" 7 | ) 8 | 9 | type Values struct { 10 | // Work around for https://github.com/kubernetes-sigs/kubebuilder/issues/528 11 | Data map[string]interface{} `json:"-"` 12 | } 13 | 14 | func (v Values) MarshalJSON() ([]byte, error) { 15 | return json.Marshal(v.Data) 16 | } 17 | 18 | func (v *Values) UnmarshalJSON(data []byte) error { 19 | var out map[string]interface{} 20 | 21 | err := json.Unmarshal(data, &out) 22 | if err != nil { 23 | return err 24 | } 25 | 26 | v.Data = out 27 | 28 | return nil 29 | } 30 | 31 | // DeepCopyInto is an deepcopy function, copying the receiver, writing 32 | // into out. In must be non-nil. Declaring this here prevents it from 33 | // being generated in `zz_generated.deepcopy.go`. 34 | // 35 | // This exists here to work around https://github.com/kubernetes/code-generator/issues/50, 36 | // and partially around https://github.com/kubernetes-sigs/controller-tools/pull/126 37 | // and https://github.com/kubernetes-sigs/controller-tools/issues/294. 38 | func (v *Values) DeepCopyInto(out *Values) { 39 | b, err := json.Marshal(v.Data) 40 | if err != nil { 41 | // The marshal should have been performed cleanly as otherwise 42 | // the resource would not have been created by the API server. 43 | panic(err) 44 | } 45 | 46 | var c map[string]interface{} 47 | 48 | err = json.Unmarshal(b, &c) 49 | if err != nil { 50 | panic(err) 51 | } 52 | 53 | out.Data = c 54 | } 55 | 56 | func (v Values) MustAsObj(obj interface{}) { 57 | err := v.AsObject(obj) 58 | if err != nil { 59 | panic(err) 60 | } 61 | } 62 | 63 | func (v Values) AsObject(obj interface{}) error { 64 | marshaled, err := json.Marshal(v) 65 | if err != nil { 66 | return fmt.Errorf("failed to marshal values: %v", err) 67 | } 68 | if err := json.Unmarshal(marshaled, obj); err != nil { 69 | return fmt.Errorf("failed to unmarshal values as obj[%s]: %v", reflect.TypeOf(obj), err) 70 | } 71 | return nil 72 | } 73 | 74 | func (v *Values) FromObject(obj interface{}) error { 75 | marshaled, err := json.Marshal(obj) 76 | if err != nil { 77 | return fmt.Errorf("failed to marshal values: %v", err) 78 | } 79 | if err := json.Unmarshal(marshaled, &v.Data); err != nil { 80 | return fmt.Errorf("failed to unmarshal values: %v", err) 81 | } 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /apis/milvus.io/v1beta1/values_types_test.go: -------------------------------------------------------------------------------- 1 | package v1beta1 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestValues_MarshalUnmarshalJSON(t *testing.T) { 10 | values := Values{ 11 | Data: map[string]interface{}{ 12 | "key": "value", 13 | }, 14 | } 15 | 16 | expected := `{"key":"value"}` 17 | actual, err := values.MarshalJSON() 18 | if err != nil { 19 | t.Errorf("unexpected error: %v", err) 20 | } 21 | assert.Equal(t, expected, string(actual)) 22 | 23 | var values2 Values 24 | err = values2.UnmarshalJSON(actual) 25 | if err != nil { 26 | t.Errorf("unexpected error: %v", err) 27 | } 28 | assert.Equal(t, values, values2) 29 | } 30 | func TestValues_DeepCopyInfo(t *testing.T) { 31 | values := &Values{ 32 | Data: map[string]interface{}{ 33 | "key": "value", 34 | }, 35 | } 36 | values2 := &Values{} 37 | values.DeepCopyInto(values2) 38 | assert.NotSame(t, values, values2) 39 | assert.NotSame(t, &values.Data, &values2.Data) 40 | assert.Equal(t, values, values2) 41 | } 42 | -------------------------------------------------------------------------------- /charts/milvus-operator/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/milvus-operator/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: cert-manager 3 | repository: https://charts.jetstack.io 4 | version: v1.5.3 5 | digest: sha256:ded312c59e9aee73e5dc268bad53029e6d7187d6ce17219b8b5d2b0ca3d0c577 6 | generated: "2024-11-19T17:22:07.833644+08:00" 7 | -------------------------------------------------------------------------------- /charts/milvus-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: milvus-operator 3 | description: A Helm chart for deploying Milvus Operator 4 | kubeVersion: '>= 1.16.0-0' 5 | 6 | home: https://github.com/zilliztech/milvus-operator 7 | 8 | # A chart can be either an 'application' or a 'library' chart. 9 | # 10 | # Application charts are a collection of templates that can be packaged into versioned archives 11 | # to be deployed. 12 | # 13 | # Library charts provide useful utilities or functions for the chart developer. They're included as 14 | # a dependency of application charts to inject those utilities and functions into the rendering 15 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 16 | type: application 17 | 18 | # This is the chart version. This version number should be incremented each time you make changes 19 | # to the chart and its templates, including the app version. 20 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 21 | version: 1.2.6 22 | 23 | # This is the version number of the application being deployed. This version number should be 24 | # incremented each time you make changes to the application. Versions are not expected to 25 | # follow Semantic Versioning. They should reflect the version the application is using. 26 | # It is recommended to use it with quotes. 27 | appVersion: "1.2.6" 28 | 29 | dependencies: 30 | - name: cert-manager 31 | version: 1.5.3 32 | repository: https://charts.jetstack.io 33 | condition: cert-manager.enabled 34 | tags: 35 | - cert-manager 36 | 37 | maintainers: 38 | - name: zilliztech 39 | email: devops@zilliz.com 40 | url: https://zilliz.com 41 | -------------------------------------------------------------------------------- /charts/milvus-operator/charts/cert-manager-v1.5.3.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilliztech/milvus-operator/37fead15c5447bb31cc86a9d45d57e820f62e265/charts/milvus-operator/charts/cert-manager-v1.5.3.tgz -------------------------------------------------------------------------------- /charts/milvus-operator/ci/default-values.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilliztech/milvus-operator/37fead15c5447bb31cc86a9d45d57e820f62e265/charts/milvus-operator/ci/default-values.yaml -------------------------------------------------------------------------------- /charts/milvus-operator/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Milvus Operator Is Starting, use `kubectl get -n {{ .Release.Namespace }} deploy/{{ .Release.Name }}` to check if its successfully installed 2 | Full Installation doc can be found in https://github.com/zilliztech/milvus-operator/blob/main/docs/installation/installation.md 3 | Quick start with `kubectl apply -f https://raw.githubusercontent.com/zilliztech/milvus-operator/main/config/samples/milvus_minimum.yaml` 4 | More samples can be found in https://github.com/zilliztech/milvus-operator/tree/main/config/samples 5 | CRD Documentation can be found in https://github.com/zilliztech/milvus-operator/tree/main/docs/CRD 6 | Administration Documentation can be found in https://github.com/zilliztech/milvus-operator/tree/main/docs/administration 7 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "chart.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 7 | {{- end }} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "chart.fullname" -}} 15 | {{- if .Values.fullnameOverride }} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 17 | {{- else }} 18 | {{- $name := default .Chart.Name .Values.nameOverride }} 19 | {{- if contains $name .Release.Name }} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 21 | {{- else }} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 23 | {{- end }} 24 | {{- end }} 25 | {{- end }} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "chart.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 32 | {{- end }} 33 | 34 | {{/* 35 | Common labels 36 | */}} 37 | {{- define "chart.labels" -}} 38 | helm.sh/chart: {{ include "chart.chart" . }} 39 | {{ include "chart.selectorLabels" . }} 40 | {{- if .Chart.AppVersion }} 41 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 42 | {{- end }} 43 | app.kubernetes.io/managed-by: {{ .Release.Service }} 44 | {{- end }} 45 | 46 | {{/* 47 | Selector labels 48 | */}} 49 | {{- define "chart.selectorLabels" -}} 50 | app.kubernetes.io/name: {{ include "chart.name" . }} 51 | app.kubernetes.io/instance: {{ .Release.Name }} 52 | {{- end }} 53 | 54 | {{/* 55 | Create the name of the service account to use 56 | */}} 57 | {{- define "chart.serviceAccountName" -}} 58 | {{- if .Values.serviceAccount.create }} 59 | {{- default (include "chart.fullname" .) .Values.serviceAccount.name }} 60 | {{- else }} 61 | {{- default "default" .Values.serviceAccount.name }} 62 | {{- end }} 63 | {{- end }} 64 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/certificate.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.enableWebhook -}} 2 | apiVersion: cert-manager.io/v1 3 | kind: Certificate 4 | metadata: 5 | name: '{{ include "chart.fullname" . }}-serving-cert' 6 | namespace: {{ .Release.Namespace }} 7 | spec: 8 | dnsNames: 9 | - milvus-operator-webhook-service.{{ .Release.Namespace }}.svc 10 | - milvus-operator-webhook-service.{{ .Release.Namespace }}.svc.cluster.local 11 | issuerRef: 12 | kind: Issuer 13 | name: '{{ include "chart.fullname" . }}-selfsigned-issuer' 14 | secretName: '{{ include "chart.fullname" . }}-webhook-cert' 15 | --- 16 | apiVersion: cert-manager.io/v1 17 | kind: Issuer 18 | metadata: 19 | name: '{{ include "chart.fullname" . }}-selfsigned-issuer' 20 | namespace: {{ .Release.Namespace }} 21 | spec: 22 | selfSigned: {} 23 | {{- end -}} 24 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.rbac.create }} 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRoleBinding 5 | metadata: 6 | name: '{{ include "chart.fullname" . }}-manager-rolebinding' 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: ClusterRole 10 | name: '{{ include "chart.fullname" . }}-manager-role' 11 | subjects: 12 | - kind: ServiceAccount 13 | name: {{ include "chart.serviceAccountName" . | quote }} 14 | namespace: {{ .Release.Namespace | quote }} 15 | {{- end -}} 16 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | labels: {{- include "chart.labels" . | nindent 4 }} 5 | name: {{ include "chart.fullname" . | quote }} 6 | namespace: {{ .Release.Namespace | quote }} 7 | spec: 8 | selector: 9 | matchLabels: {{- include "chart.selectorLabels" . | nindent 6 }} 10 | template: 11 | metadata: 12 | annotations: {{- toYaml .Values.podAnnotations | nindent 8 }} 13 | labels: {{- include "chart.selectorLabels" . | nindent 8 }} 14 | spec: 15 | affinity: {{- toYaml .Values.affinity | nindent 8 }} 16 | containers: 17 | - args: 18 | - -namespace 19 | - {{ .Release.Namespace | quote }} 20 | - -name 21 | - {{ include "chart.fullname" . | quote }} 22 | - --health-probe-bind-address=:8081 23 | - --metrics-bind-address=:8080 24 | - --leader-elect 25 | {{- if .Values.enableWebhook }} 26 | - --webhook=true 27 | {{- end }} 28 | command: 29 | - /manager 30 | image: '{{.Values.image.repository}}:{{.Values.image.tag|default .Chart.AppVersion}}' 31 | imagePullPolicy: {{ .Values.image.pullPolicy | quote }} 32 | livenessProbe: 33 | httpGet: 34 | path: /healthz 35 | port: 8081 36 | initialDelaySeconds: 15 37 | periodSeconds: 20 38 | name: manager 39 | ports: 40 | - containerPort: 9443 41 | name: webhook-server 42 | protocol: TCP 43 | - containerPort: 8080 44 | name: metrics 45 | protocol: TCP 46 | readinessProbe: 47 | httpGet: 48 | path: /readyz 49 | port: 8081 50 | initialDelaySeconds: 5 51 | periodSeconds: 10 52 | resources: {{- toYaml .Values.resources | nindent 10 }} 53 | securityContext: 54 | allowPrivilegeEscalation: {{ .Values.allowPrivilegeEscalation }} 55 | {{- if .Values.enableWebhook }} 56 | volumeMounts: 57 | - mountPath: /tmp/k8s-webhook-server/serving-certs 58 | name: cert 59 | readOnly: true 60 | {{- end }} 61 | imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }} 62 | nodeSelector: {{- toYaml .Values.nodeSelector | nindent 8 }} 63 | securityContext: {{- toYaml .Values.podSecurityContext | nindent 8 }} 64 | serviceAccountName: {{ include "chart.serviceAccountName" . | quote }} 65 | terminationGracePeriodSeconds: 10 66 | tolerations: {{- toYaml .Values.tolerations | nindent 8 }} 67 | {{- if .Values.enableWebhook }} 68 | volumes: 69 | - name: cert 70 | secret: 71 | defaultMode: 420 72 | secretName: {{ include "chart.fullname" . }}-webhook-cert 73 | {{- end }} 74 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/mutatingwebhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.enableWebhook }} 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 8 | name: '{{ include "chart.fullname" . }}-mutating-webhook-configuration' 9 | webhooks: 10 | - admissionReviewVersions: 11 | - v1 12 | clientConfig: 13 | service: 14 | name: '{{ include "chart.fullname" . }}-webhook-service' 15 | namespace: {{ .Release.Namespace | quote }} 16 | path: /mutate-milvus-io-v1beta1-milvus 17 | port: 443 18 | failurePolicy: Fail 19 | name: mmilvus.kb.io 20 | rules: 21 | - apiGroups: 22 | - milvus.io 23 | apiVersions: 24 | - v1beta1 25 | operations: 26 | - CREATE 27 | - UPDATE 28 | resources: 29 | - milvuses 30 | sideEffects: None 31 | - admissionReviewVersions: 32 | - v1 33 | clientConfig: 34 | service: 35 | name: '{{ include "chart.fullname" . }}-webhook-service' 36 | namespace: {{ .Release.Namespace | quote }} 37 | path: /mutate-milvus-io-v1beta1-milvusupgrade 38 | failurePolicy: Fail 39 | name: mmilvusupgrade.kb.io 40 | rules: 41 | - apiGroups: 42 | - milvus.io 43 | apiVersions: 44 | - v1beta1 45 | operations: 46 | - CREATE 47 | - UPDATE 48 | resources: 49 | - milvusupgrades 50 | sideEffects: None 51 | {{- end -}} 52 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/role.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.rbac.create }} 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: Role 5 | metadata: 6 | name: '{{ include "chart.fullname" . }}-leader-election-role' 7 | namespace: {{ .Release.Namespace | quote }} 8 | rules: 9 | - apiGroups: 10 | - "" 11 | resources: 12 | - configmaps 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - coordination.k8s.io 23 | resources: 24 | - leases 25 | verbs: 26 | - get 27 | - list 28 | - watch 29 | - create 30 | - update 31 | - patch 32 | - delete 33 | - apiGroups: 34 | - "" 35 | resources: 36 | - events 37 | verbs: 38 | - create 39 | - patch 40 | {{- end -}} 41 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/rolebinding.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.rbac.create }} 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: RoleBinding 5 | metadata: 6 | name: '{{ include "chart.fullname" . }}-leader-election-rolebinding' 7 | namespace: {{ .Release.Namespace | quote }} 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: '{{ include "chart.fullname" . }}-leader-election-role' 12 | subjects: 13 | - kind: ServiceAccount 14 | name: {{ include "chart.serviceAccountName" . | quote }} 15 | namespace: {{ .Release.Namespace | quote }} 16 | {{- end -}} 17 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | service-kind: metrics 6 | {{- include "chart.labels" . | nindent 4 }} 7 | name: '{{ include "chart.fullname" . }}-metrics-service' 8 | namespace: {{ .Release.Namespace | quote }} 9 | spec: 10 | ports: 11 | - name: metrics 12 | port: 8443 13 | targetPort: metrics 14 | selector: 15 | {{- include "chart.selectorLabels" . | nindent 4 }} 16 | --- 17 | apiVersion: v1 18 | kind: Service 19 | metadata: 20 | labels: 21 | {{- include "chart.labels" . | nindent 4 }} 22 | name: '{{ include "chart.fullname" . }}-webhook-service' 23 | namespace: {{ .Release.Namespace | quote }} 24 | spec: 25 | ports: 26 | - port: 443 27 | targetPort: webhook-server 28 | protocol: TCP 29 | name: https 30 | selector: 31 | {{- include "chart.selectorLabels" . | nindent 4 }} 32 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "chart.serviceAccountName" . | quote }} 6 | namespace: {{ .Release.Namespace | quote }} 7 | labels: 8 | {{- include "chart.labels" . | nindent 4 }} 9 | {{- with .Values.serviceAccount.annotations }} 10 | annotations: 11 | {{- toYaml . | nindent 4 }} 12 | {{- end }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.monitoringEnabled -}} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | {{- include "chart.labels" . | nindent 4 }} 7 | name: '{{ include "chart.fullname" . }}-metrics-monitor' 8 | namespace: {{ .Release.Namespace | quote }} 9 | spec: 10 | endpoints: 11 | - path: /metrics 12 | port: metrics 13 | scheme: http 14 | selector: 15 | matchLabels: 16 | service-kind: metrics 17 | {{- include "chart.selectorLabels" . | nindent 6 }} 18 | namespaceSelector: 19 | matchNames: 20 | - {{ .Release.Namespace | quote }} 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /charts/milvus-operator/templates/validatingwebhookconfiguration.yaml: -------------------------------------------------------------------------------- 1 | {{- /* Code generated by make. DO NOT EDIT. */ -}} 2 | {{- if .Values.enableWebhook }} 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: ValidatingWebhookConfiguration 5 | metadata: 6 | annotations: 7 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 8 | name: '{{ include "chart.fullname" . }}-validating-webhook-configuration' 9 | webhooks: 10 | - admissionReviewVersions: 11 | - v1 12 | clientConfig: 13 | service: 14 | name: '{{ include "chart.fullname" . }}-webhook-service' 15 | namespace: {{ .Release.Namespace | quote }} 16 | path: /validate-milvus-io-v1beta1-milvus 17 | port: 443 18 | failurePolicy: Fail 19 | name: vmilvus.kb.io 20 | rules: 21 | - apiGroups: 22 | - milvus.io 23 | apiVersions: 24 | - v1beta1 25 | operations: 26 | - CREATE 27 | - UPDATE 28 | resources: 29 | - milvuses 30 | sideEffects: None 31 | - admissionReviewVersions: 32 | - v1 33 | clientConfig: 34 | service: 35 | name: '{{ include "chart.fullname" . }}-webhook-service' 36 | namespace: {{ .Release.Namespace | quote }} 37 | path: /validate-milvus-io-v1beta1-milvusupgrade 38 | failurePolicy: Fail 39 | name: vmilvusupgrade.kb.io 40 | rules: 41 | - apiGroups: 42 | - milvus.io 43 | apiVersions: 44 | - v1beta1 45 | operations: 46 | - CREATE 47 | - UPDATE 48 | resources: 49 | - milvusupgrades 50 | sideEffects: None 51 | {{- end -}} 52 | -------------------------------------------------------------------------------- /codecov.yaml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "**/zz_generated.deepcopy.go" 3 | - "**/*_mock.go" 4 | - "tool/**" 5 | - "test/**" 6 | - "apis/v1alpha1/milvus.io/v1alpha1/**" 7 | - "pkg/client/**" 8 | - "pkg/controller/milvuscluster/**" 9 | - "pkg/external/iam/**" 10 | coverage: 11 | status: 12 | project: 13 | default: 14 | target: 75% 15 | patch: 16 | default: 17 | target: 20% 18 | -------------------------------------------------------------------------------- /config/assets/templates/migration.yaml.tmpl: -------------------------------------------------------------------------------- 1 | cmd: 2 | type: {{ .Command }} 3 | 4 | config: 5 | sourceVersion: {{ .SourceVersion }} 6 | targetVersion: {{ .TargetVersion }} 7 | backupFilePath: /milvus/data/migration.bak 8 | 9 | metastore: 10 | type: etcd 11 | 12 | etcd: 13 | {{- range .Endpoints }} 14 | endpoints: 15 | - {{ .}} 16 | {{- end }} 17 | rootPath: {{ .RootPath }} 18 | metaSubPath: {{ .MetaSubPath | default "meta" }} 19 | kvSubPath: {{ .KvSubPath | default "kv" }} 20 | -------------------------------------------------------------------------------- /config/assets/templates/milvus-cluster.yaml.tmpl: -------------------------------------------------------------------------------- 1 | etcd: 2 | {{- range .Spec.Dep.Etcd.Endpoints }} 3 | endpoints: 4 | - {{ .}} 5 | {{- end }} 6 | rootPath: {{ .Name }} 7 | minio: 8 | address: localhost 9 | port: 9000 10 | useSSL: false 11 | bucketName: {{ .Name }} 12 | rootPath: files 13 | 14 | pulsar: 15 | address: localhost 16 | port: 6650 17 | maxMessageSize: 5242880 # 5 * 1024 * 1024 Bytes 18 | 19 | kafka: 20 | {{- range .Spec.Dep.Kafka.BrokerList }} 21 | brokerList: 22 | - {{ .}} 23 | {{- end }} 24 | 25 | rootCoord: 26 | port: {{ .Spec.Com.RootCoord.Port | default 53100 }} 27 | 28 | proxy: 29 | port: {{ .Spec.Com.Proxy.Port | default 19530 }} 30 | 31 | queryCoord: 32 | port: {{ .Spec.Com.QueryCoord.Port | default 19531 }} 33 | 34 | queryNode: 35 | port: {{ .Spec.Com.QueryNode.Port | default 21123 }} 36 | 37 | indexCoord: 38 | port: {{ .Spec.Com.IndexCoord.Port | default 31000 }} 39 | 40 | indexNode: 41 | port: {{ .Spec.Com.IndexNode.Port | default 21121 }} 42 | 43 | dataCoord: 44 | port: {{ .Spec.Com.DataCoord.Port | default 13333 }} 45 | 46 | dataNode: 47 | port: {{ .Spec.Com.DataNode.Port | default 21124 }} 48 | 49 | msgChannel: 50 | chanNamePrefix: 51 | cluster: {{ .Name }} 52 | -------------------------------------------------------------------------------- /config/assets/templates/milvus.yaml.tmpl: -------------------------------------------------------------------------------- 1 | etcd: 2 | {{- range .Spec.Dep.Etcd.Endpoints }} 3 | endpoints: 4 | - {{ .}} 5 | {{- end }} 6 | rootPath: {{ .Name }} 7 | 8 | minio: 9 | bucketName: {{ .Name }} 10 | 11 | msgChannel: 12 | chanNamePrefix: 13 | cluster: {{ .Name }} 14 | -------------------------------------------------------------------------------- /config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Shanghai 11 | L = Shanghai 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/milvus.io_milvuses.yaml 6 | - bases/milvus.io_milvusclusters.yaml 7 | - bases/milvus.io_milvusupgrades.yaml 8 | #+kubebuilder:scaffold:crdkustomizeresource 9 | 10 | patchesStrategicMerge: 11 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 12 | # patches here are for enabling the conversion webhook for each CRD 13 | - patches/webhook_in_milvuses.yaml 14 | #- patches/webhook_in_milvusupgrades.yaml 15 | #+kubebuilder:scaffold:crdkustomizewebhookpatch 16 | 17 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 18 | # patches here are for enabling the CA injection for each CRD 19 | - patches/cainjection_in_milvuses.yaml 20 | #- patches/cainjection_in_milvusupgrades.yaml 21 | #+kubebuilder:scaffold:crdkustomizecainjectionpatch 22 | 23 | # the following config is for teaching kustomize how to do kustomization for CRDs. 24 | configurations: 25 | - kustomizeconfig.yaml 26 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_milvuses.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: milvus-operator/milvus-operator-serving-cert 7 | name: milvuses.milvus.io 8 | -------------------------------------------------------------------------------- /config/crd/patches/cainjection_in_milvusupgrades.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: milvusupgrades.milvus.io 8 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_milvuses.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: milvuses.milvus.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/crd/patches/webhook_in_milvusupgrades.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: milvusupgrades.milvus.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: milvus-operator 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: milvus-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #commonLabels: 13 | # someName: someValue 14 | 15 | bases: 16 | - ../crd 17 | - ../rbac 18 | - ../manager 19 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 20 | # crd/kustomization.yaml 21 | - ../webhook 22 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 23 | # - ../certmanager 24 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 25 | #- ../prometheus 26 | 27 | patchesStrategicMerge: 28 | # Protect the /metrics endpoint by putting it behind auth. 29 | # If you want your controller-manager to expose the /metrics 30 | # endpoint w/o any authn/z, please comment the following line. 31 | - manager_auth_proxy_patch.yaml 32 | 33 | # Mount the controller config file for loading manager configurations 34 | # through a ComponentConfig type 35 | #- manager_config_patch.yaml 36 | 37 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 38 | # crd/kustomization.yaml 39 | - manager_webhook_patch.yaml 40 | 41 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 42 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 43 | # 'CERTMANAGER' needs to be enabled to use ca injection 44 | - webhookcainjection_patch.yaml 45 | 46 | vars: 47 | - name: DEPLOYMENT_NAMESPACE # namespace of the deployment 48 | objref: 49 | kind: Deployment 50 | group: apps 51 | version: v1 52 | name: controller-manager # this name should match the one in manager.yaml 53 | fieldref: 54 | fieldpath: metadata.namespace 55 | - name: DEPLOYMENT_NAME 56 | objref: 57 | kind: Deployment 58 | group: apps 59 | version: v1 60 | name: controller-manager # this name should match the one in manager.yaml -------------------------------------------------------------------------------- /config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | spec: 8 | template: 9 | spec: 10 | containers: 11 | - name: manager 12 | args: 13 | - -namespace 14 | - $(DEPLOYMENT_NAMESPACE) 15 | - -name 16 | - $(DEPLOYMENT_NAME) 17 | - "--health-probe-bind-address=:8081" 18 | - "--metrics-bind-address=:8080" 19 | - "--leader-elect" 20 | -------------------------------------------------------------------------------- /config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: manager 10 | args: 11 | - "--config=controller_manager_config.yaml" 12 | volumeMounts: 13 | - name: manager-config 14 | mountPath: /controller_manager_config.yaml 15 | subPath: controller_manager_config.yaml 16 | volumes: 17 | - name: manager-config 18 | configMap: 19 | name: manager-config 20 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: manager 10 | ports: 11 | - containerPort: 9443 12 | name: webhook-server 13 | protocol: TCP 14 | - containerPort: 8080 15 | name: metrics 16 | protocol: TCP 17 | -------------------------------------------------------------------------------- /config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: milvus-operator/milvus-operator-serving-cert 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: milvus-operator/milvus-operator-serving-cert 16 | -------------------------------------------------------------------------------- /config/dev/debug_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: milvus-operator-debug 5 | namespace: milvus-operator 6 | spec: 7 | ports: 8 | - nodePort: 31666 9 | port: 31666 10 | protocol: TCP 11 | targetPort: 31666 12 | selector: 13 | control-plane: controller-manager 14 | type: NodePort -------------------------------------------------------------------------------- /config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | - debug_service.yaml 4 | 5 | patchesStrategicMerge: 6 | - manager_dev_patch.yaml 7 | -------------------------------------------------------------------------------- /config/dev/manager_dev_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: manager 13 | env: 14 | - name: GOPROXY 15 | value: https://goproxy.cn 16 | - name: DEBUG 17 | value: 'true' -------------------------------------------------------------------------------- /config/dev/webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | - op: "remove" 2 | path: "/metadata/annotations/cert-manager.io~1inject-ca-from" 3 | - op: "remove" 4 | path: "/webhooks/0/clientConfig/service" -------------------------------------------------------------------------------- /config/helm/certificate/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: '{{ .Release.Namespace | quote }}' 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | patchesStrategicMerge: 9 | - patch_certificate_dns.yaml 10 | - patch_certificate_secret.yaml 11 | 12 | bases: 13 | - ../../certmanager 14 | -------------------------------------------------------------------------------- /config/helm/certificate/patch_certificate_dns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | name: serving-cert 5 | spec: 6 | dnsNames: 7 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc' 8 | - '{{ include "chart.fullname" . }}-webhook-service.{{ .Release.Namespace }}.svc.cluster.local' 9 | -------------------------------------------------------------------------------- /config/helm/certificate/patch_certificate_secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | name: serving-cert 5 | spec: 6 | secretName: '{{ include "chart.fullname" . }}-webhook-cert' 7 | -------------------------------------------------------------------------------- /config/helm/crds/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: '{{ .Release.Namespace }}' 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | commonAnnotations: 9 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 10 | 11 | patchesStrategicMerge: 12 | - webhook_patch.yaml 13 | 14 | bases: 15 | - ../../crd 16 | -------------------------------------------------------------------------------- /config/helm/crds/webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: milvuses.milvus.io 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: '{{.Release.Namespace}}' 13 | name: '{{. | include "chart.fullname"}}-webhook-service' 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /config/helm/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: '{{ .Release.Namespace | quote }}' 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | patches: 9 | - patch_leaderelection_binding.yaml 10 | - patch_manager_binding.yaml 11 | 12 | bases: 13 | - ../../rbac 14 | -------------------------------------------------------------------------------- /config/helm/rbac/patch_leaderelection_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: 'leader-election-rolebinding' 5 | subjects: 6 | - kind: ServiceAccount 7 | name: '{{ include "chart.serviceAccountName" . | quote }}' 8 | namespace: '{{ .Release.Namespace | quote }}' 9 | -------------------------------------------------------------------------------- /config/helm/rbac/patch_manager_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | subjects: 6 | - kind: ServiceAccount 7 | name: '{{ include "chart.serviceAccountName" . | quote }}' 8 | namespace: '{{ .Release.Namespace | quote }}' 9 | -------------------------------------------------------------------------------- /config/helm/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | namePrefix: '{{ include "chart.fullname" . }}-' 2 | 3 | namespace: '{{ .Release.Namespace | quote }}' 4 | 5 | generatorOptions: 6 | disableNameSuffixHash: true 7 | 8 | commonAnnotations: 9 | # Trick so kustomize does not split the annotation value 10 | cert-manager.io/inject-ca-from: '{{.Release.Namespace}}/{{. | include "chart.fullname"}}-serving-cert' 11 | 12 | patchesStrategicMerge: 13 | - validatingwebhook_endpoint_patch.yaml 14 | - mutatingwebhook_endpoint_patch.yaml 15 | 16 | bases: 17 | - ../../webhook 18 | -------------------------------------------------------------------------------- /config/helm/webhook/mutatingwebhook_endpoint_patch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: mutating-webhook-configuration 6 | webhooks: 7 | - name: mmilvus.kb.io 8 | clientConfig: 9 | service: 10 | name: '{{ include "chart.fullname" . }}-webhook-service' 11 | namespace: '{{ .Release.Namespace | quote }}' 12 | port: 443 13 | 14 | -------------------------------------------------------------------------------- /config/helm/webhook/validatingwebhook_endpoint_patch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: ValidatingWebhookConfiguration 4 | metadata: 5 | name: validating-webhook-configuration 6 | webhooks: 7 | - name: vmilvus.kb.io 8 | clientConfig: 9 | service: 10 | name: '{{ include "chart.fullname" . }}-webhook-service' 11 | namespace: '{{ .Release.Namespace | quote }}' 12 | port: 443 13 | 14 | -------------------------------------------------------------------------------- /config/kind/kind-dev.yaml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | -------------------------------------------------------------------------------- /config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: :8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 71808ec5.milvus.io 12 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | images: 4 | - name: controller 5 | newName: milvusdb/milvus-operator 6 | newTag: main-latest 7 | 8 | resources: 9 | - namespace.yaml 10 | 11 | generatorOptions: 12 | disableNameSuffixHash: true 13 | 14 | configMapGenerator: 15 | - files: 16 | - controller_manager_config.yaml 17 | name: manager-config 18 | -------------------------------------------------------------------------------- /config/manager/namespace.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: "v1" 2 | kind: Namespace 3 | metadata: 4 | name: milvus-operator 5 | -------------------------------------------------------------------------------- /config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | -------------------------------------------------------------------------------- /config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | spec: 8 | ports: 9 | - name: https 10 | port: 8443 11 | targetPort: https 12 | selector: 13 | control-plane: controller-manager 14 | -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | # - auth_proxy_service.yaml 16 | # - auth_proxy_role.yaml 17 | # - auth_proxy_role_binding.yaml 18 | # - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch 38 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/milvus_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit milvus. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: milvus-editor-role 6 | rules: 7 | - apiGroups: 8 | - milvus.io 9 | resources: 10 | - milvuses 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - milvus.io 21 | resources: 22 | - milvus/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /config/rbac/milvus_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view milvus. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: milvus-viewer-role 6 | rules: 7 | - apiGroups: 8 | - milvus.io 9 | resources: 10 | - milvuses 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - milvus.io 17 | resources: 18 | - milvuses/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /config/rbac/milvusupgrade_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit milvusupgrades. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: milvusupgrade-editor-role 6 | rules: 7 | - apiGroups: 8 | - milvus.io 9 | resources: 10 | - milvusupgrades 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - milvus.io 21 | resources: 22 | - milvusupgrades/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /config/rbac/milvusupgrade_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view milvusupgrades. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: milvusupgrade-viewer-role 6 | rules: 7 | - apiGroups: 8 | - milvus.io 9 | resources: 10 | - milvusupgrades 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - milvus.io 17 | resources: 18 | - milvusupgrades/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /config/samples/beta/README.md: -------------------------------------------------------------------------------- 1 | # Beta Samples 2 | Samples in this folder is not formally released. 3 | It uses the dev image of milvus. 4 | Be aware of the potential issues. 5 | -------------------------------------------------------------------------------- /config/samples/beta/milvus_streaming_node.yaml: -------------------------------------------------------------------------------- 1 | # the manifest to enable streaming node for milvus cluster mode 2 | # ref https://milvus.io/docs/release_notes.md#Streaming-Node-Beta 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: milvus 7 | namespace: mc-sit 8 | labels: 9 | app: milvus 10 | spec: 11 | mode: 'cluster' 12 | components: 13 | enableRollingUpdate: false 14 | image: milvusdb/milvus:v2.5.11 15 | dependencies: 16 | msgStreamType: pulsar # for now only support pulsar 17 | -------------------------------------------------------------------------------- /config/samples/beta/milvus_woodpecker.yaml: -------------------------------------------------------------------------------- 1 | # the manifest to enable streaming node for milvus cluster mode 2 | # ref https://milvus.io/docs/release_notes.md#Streaming-Node-Beta 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: milvus 7 | namespace: mc-sit 8 | labels: 9 | app: milvus 10 | spec: 11 | mode: 'cluster' 12 | components: 13 | # image not formally released yet 14 | image: harbor.milvus.io/milvus/milvus:tinswzy-support_woodpecker_wal_type-36319c0-20250326 15 | streamingNode: 16 | replicas: 1 17 | indexNode: 18 | replicas: 0 19 | dependencies: 20 | msgStreamType: woodpecker 21 | -------------------------------------------------------------------------------- /config/samples/cluster_demo.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus cluster with minimum cost of resources. 2 | # It should be used for testing and development purposes only. 3 | # Total resources required is about: 0.25 CPU, 512 MiB memory 4 | # When deleted, all the data in the Milvus will be lost. 5 | 6 | apiVersion: milvus.io/v1beta1 7 | kind: Milvus 8 | metadata: 9 | name: my-release 10 | labels: 11 | app: milvus 12 | spec: 13 | mode: cluster 14 | config: {} 15 | components: 16 | enableRollingUpdate: true 17 | imageUpdateMode: rollingUpgrade 18 | proxy: 19 | replicas: 1 20 | serviceType: LoadBalancer 21 | dataNode: 22 | replicas: 1 23 | indexNode: 24 | replicas: 1 25 | queryNode: 26 | replicas: 1 27 | mixCoord: 28 | replicas: 1 29 | dependencies: 30 | etcd: 31 | inCluster: 32 | values: 33 | replicaCount: 1 34 | deletionPolicy: Delete 35 | pvcDeletion: true 36 | storage: 37 | inCluster: 38 | values: 39 | mode: standalone 40 | resources: 41 | requests: 42 | memory: 100Mi 43 | persistence: 44 | size: 20Gi 45 | deletionPolicy: Delete 46 | pvcDeletion: true 47 | msgStreamType: kafka 48 | kafka: 49 | inCluster: 50 | values: 51 | defaultReplicationFactor: 1 52 | offsetsTopicReplicationFactor: 1 53 | replicaCount: 1 54 | zookeeper: 55 | replicaCount: 1 56 | deletionPolicy: Delete 57 | pvcDeletion: true 58 | -------------------------------------------------------------------------------- /config/samples/demo.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus cluster with minimum cost of resources. 2 | # It should be used for testing and development purposes only. 3 | # Total resources required is about: 0.1 CPU, 100 MiB memory 4 | # When deleted, all the data in the Milvus will be lost. 5 | 6 | apiVersion: milvus.io/v1beta1 7 | kind: Milvus 8 | metadata: 9 | name: my-release 10 | labels: 11 | app: milvus 12 | spec: 13 | config: {} 14 | components: 15 | standalone: 16 | replicas: 1 17 | serviceType: LoadBalancer 18 | dependencies: 19 | etcd: 20 | inCluster: 21 | values: 22 | replicaCount: 1 23 | deletionPolicy: Delete 24 | pvcDeletion: true 25 | storage: 26 | inCluster: 27 | values: 28 | mode: standalone 29 | resources: 30 | requests: 31 | memory: 100Mi 32 | persistence: 33 | size: 20Gi 34 | deletionPolicy: Delete 35 | pvcDeletion: true 36 | -------------------------------------------------------------------------------- /config/samples/external_tls.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to enable external tls 2 | --- 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: certs 7 | type: Opaque 8 | stringData: 9 | # change data to your own certificates 10 | # If you don't have your own certificates, you can create them by following the instructions in the link below 11 | # https://milvus.io/docs/tls.md#Create-your-own-certificate 12 | server.pem: | 13 | -----BEGIN CERTIFICATE----- 14 | change to your own certificate 15 | -----END CERTIFICATE----- 16 | server.key: 17 | -----BEGIN RSA PRIVATE KEY----- 18 | change to your own private key 19 | -----END RSA PRIVATE KEY----- 20 | ca.pem: 21 | -----BEGIN CERTIFICATE----- 22 | change to your own ca certificate 23 | -----END CERTIFICATE----- 24 | --- 25 | apiVersion: milvus.io/v1beta1 26 | kind: Milvus 27 | metadata: 28 | name: my-release 29 | labels: 30 | app: milvus 31 | spec: 32 | config: 33 | proxy: 34 | http: 35 | # for now not support config restful on same port with grpc 36 | # so we set to 8080, grpc will still use 19530 37 | port: 8080 38 | common: 39 | security: 40 | tlsMode: 1 # set to 2 to enable Mutual TLS 41 | # Configure the proxy tls certificates 42 | # if this field not set, it will use the self signed localhost certificates within the image 43 | tls: 44 | serverPemPath: /certs/server.pem 45 | serverKeyPath: /certs/server.key 46 | caPemPath: /certs/ca.pem 47 | components: 48 | # mount the certs secret to the milvus container 49 | volumes: 50 | - name: certs 51 | secret: 52 | secretName: certs 53 | volumeMounts: 54 | - name: certs 55 | mountPath: /certs 56 | readOnly: true 57 | -------------------------------------------------------------------------------- /config/samples/hpa.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a standalone milvus in milvus-operator's default configurations. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | spec: 7 | mode: cluster 8 | components: 9 | proxy: 10 | # set replicas to -1 will stop operator from scaling the component 11 | # thus handover the scaling responsibility to HPA 12 | replicas: -1 13 | --- 14 | # for more info see: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ 15 | apiVersion: autoscaling/v2 16 | kind: HorizontalPodAutoscaler 17 | metadata: 18 | name: my-release-milvus-proxy-hpa 19 | spec: 20 | scaleTargetRef: 21 | apiVersion: apps/v1 22 | kind: Deployment 23 | name: my-release-milvus-proxy 24 | minReplicas: 2 25 | maxReplicas: 10 26 | metrics: 27 | - type: Resource 28 | resource: 29 | name: cpu 30 | target: 31 | type: Utilization 32 | averageUtilization: 60 33 | - type: Resource 34 | resource: 35 | name: memory 36 | target: 37 | type: Utilization 38 | averageUtilization: 60 39 | behavior: 40 | scaleUp: 41 | policies: 42 | - type: Pods 43 | value: 1 44 | periodSeconds: 30 45 | scaleDown: 46 | stabilizationWindowSeconds: 300 47 | policies: 48 | - type: Pods 49 | value: 1 50 | periodSeconds: 60 51 | -------------------------------------------------------------------------------- /config/samples/internal_tls.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to enable external tls 2 | --- 3 | apiVersion: v1 4 | kind: Secret 5 | metadata: 6 | name: certs 7 | type: Opaque 8 | # change data to your own certificates 9 | # If you don't have your own certificates, you can create them by following the instructions in the link below 10 | # https://milvus.io/docs/tls.md#Create-your-own-certificate 11 | stringData: 12 | server.pem: | 13 | -----BEGIN CERTIFICATE----- 14 | change to your own certificate 15 | -----END CERTIFICATE----- 16 | server.key: 17 | -----BEGIN RSA PRIVATE KEY----- 18 | change to your own private key 19 | -----END RSA PRIVATE KEY----- 20 | ca.pem: 21 | -----BEGIN CERTIFICATE----- 22 | change to your own ca certificate 23 | -----END CERTIFICATE----- 24 | --- 25 | apiVersion: milvus.io/v1beta1 26 | kind: Milvus 27 | metadata: 28 | name: my-release 29 | labels: 30 | app: milvus 31 | spec: 32 | config: 33 | common: 34 | security: 35 | internaltlsEnabled: true 36 | # Configure internal tls certificates 37 | # if this field not set, it will use the self signed localhost certificates within the image 38 | internaltls: 39 | serverPemPath: /certs/server.pem 40 | serverKeyPath: /certs/server.key 41 | caPemPath: /certs/ca.pem 42 | sni: localhost # change to your own certificate's hostname 43 | components: 44 | # mount the certs secret to the milvus container 45 | volumes: 46 | - name: certs 47 | secret: 48 | secretName: certs 49 | volumeMounts: 50 | - name: certs 51 | mountPath: /certs 52 | readOnly: true 53 | -------------------------------------------------------------------------------- /config/samples/milvus_azure_blob_accesskey.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with Azure Storage as its object storage with access-key. 2 | # change the to match your environment 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | config: 11 | common: 12 | storageType: remote 13 | minio: 14 | cloudProvider: azure 15 | bucketName: 16 | rootPath: milvus/my-release 17 | useSSL: true 18 | dependencies: 19 | storage: 20 | external: true 21 | type: Azure 22 | endpoint: core.windows.net:443 23 | secretRef: "my-release-azure-secret" 24 | --- 25 | apiVersion: v1 26 | kind: Secret 27 | metadata: 28 | name: my-release-azure-secret 29 | type: Opaque 30 | stringData: 31 | accesskey: 32 | secretkey: 33 | -------------------------------------------------------------------------------- /config/samples/milvus_azure_blob_connection_string.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with Azure Storage as its object storage with connection string. 2 | # change the to match your environment 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | components: 11 | env: 12 | - name: AZURE_CONNECTION_STRING 13 | value: 14 | config: 15 | common: 16 | storageType: remote 17 | minio: 18 | cloudProvider: azure 19 | bucketName: 20 | rootPath: milvus/my-release 21 | accessKeyID: 22 | useSSL: true 23 | dependencies: 24 | storage: 25 | external: true 26 | type: Azure 27 | endpoint: core.windows.net:443 28 | -------------------------------------------------------------------------------- /config/samples/milvus_azure_blob_iam.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with Azure Storage as its object storage with AD workload identity. 2 | # see: https://azure.github.io/azure-workload-identity/docs/ for detail 3 | # change the to match your environment 4 | apiVersion: milvus.io/v1beta1 5 | kind: Milvus 6 | metadata: 7 | name: my-release 8 | labels: 9 | app: milvus 10 | spec: 11 | config: 12 | common: 13 | storageType: remote 14 | minio: 15 | cloudProvider: azure 16 | bucketName: 17 | rootPath: milvus/my-release 18 | useSSL: true 19 | useIAM: true 20 | accessKeyID: 21 | components: 22 | serviceAccountName: my-release-sa 23 | podLabels: 24 | azure.workload.identity/use: "true" 25 | dependencies: 26 | storage: 27 | external: true 28 | type: Azure 29 | endpoint: core.windows.net:443 30 | --- 31 | apiVersion: v1 32 | kind: ServiceAccount 33 | metadata: 34 | name: my-release-sa 35 | annotations: 36 | azure.workload.identity/client-id: 37 | -------------------------------------------------------------------------------- /config/samples/milvus_cluster_4coords.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus cluster using 2 | # rootCoord, indexCoord, dataCoord and queryCoord instead of mixCoord. 3 | 4 | apiVersion: milvus.io/v1beta1 5 | kind: Milvus 6 | metadata: 7 | name: my-release 8 | labels: 9 | app: milvus 10 | spec: 11 | mode: cluster 12 | dependencies: {} 13 | components: 14 | rootCoord: 15 | replicas: 1 16 | config: {} -------------------------------------------------------------------------------- /config/samples/milvus_cluster_default.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus cluster in milvus-operator's default configurations. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | mode: cluster 10 | dependencies: {} 11 | components: {} 12 | config: {} -------------------------------------------------------------------------------- /config/samples/milvus_cluster_mixcoord.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus cluster using mixCoord instead of rootCoord, indexCoord, dataCoord and queryCoord. 2 | 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | mode: cluster 11 | dependencies: {} 12 | components: 13 | # now mixCoord is used by default 14 | # mixCoord deploys all coordinators in one 'mixture' deployment 15 | mixCoord: 16 | replicas: 1 17 | config: {} -------------------------------------------------------------------------------- /config/samples/milvus_cluster_resource.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to configure a milvus cluster's cpu and memory resources. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | mode: cluster 10 | components: 11 | resources: 12 | limits: 13 | cpu: '4' 14 | memory: 8Gi 15 | requests: 16 | cpu: 200m 17 | memory: 512Mi 18 | dataCoord: 19 | replicas: 1 20 | dataNode: 21 | replicas: 1 22 | indexCoord: 23 | replicas: 1 24 | indexNode: 25 | replicas: 1 26 | proxy: 27 | replicas: 1 28 | serviceType: LoadBalancer 29 | resources: 30 | limits: 31 | cpu: '2' 32 | memory: 4Gi 33 | requests: 34 | cpu: 100m 35 | memory: 128Mi 36 | queryCoord: 37 | replicas: 1 38 | queryNode: 39 | replicas: 1 40 | rootCoord: 41 | replicas: 1 42 | config: {} 43 | dependencies: {} -------------------------------------------------------------------------------- /config/samples/milvus_config.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to add custom configurations for milvus 2 | # It changes the etcd's rootPath, minio's bucketName and log's level 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | dependencies: {} 11 | components: {} 12 | # check full configuration options at https://github.com/milvus-io/milvus/blob/master/configs/milvus.yaml 13 | config: 14 | etcd: 15 | rootPath: my-release 16 | minio: 17 | bucketName: my-bucket 18 | log: 19 | level: debug -------------------------------------------------------------------------------- /config/samples/milvus_config_dynamic.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to use dynamic configurations for milvus 2 | # note milvus version has to be v2.3.0 or later 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | dependencies: {} 11 | components: 12 | # make operator only update configMap when change spec.config field 13 | updateConfigMapOnly: true 14 | config: 15 | # for allowed dynamic fields 16 | # check https://milvus.io/docs/dynamic_config.md for latest version 17 | # check https://milvus.io/docs/v2.3.x/dynamic_config.md for v2.3 18 | # eg: change the max size of disk segment to 4096 19 | dataCoord: 20 | segment: 21 | diskSegmentMaxSize: 4096 # default is 2048 22 | -------------------------------------------------------------------------------- /config/samples/milvus_default.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a standalone milvus in milvus-operator's default configurations. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release -------------------------------------------------------------------------------- /config/samples/milvus_deletion.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus, that deletes all its dependencies and storage when the milvus is deleted. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | mode: cluster 10 | dependencies: 11 | etcd: 12 | inCluster: 13 | deletionPolicy: Delete 14 | pvcDeletion: true 15 | storage: 16 | inCluster: 17 | deletionPolicy: Delete 18 | pvcDeletion: true -------------------------------------------------------------------------------- /config/samples/milvus_etcd_auth.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to enable etcd auth for milvus 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | dependencies: 10 | etcd: 11 | inCluster: 12 | values: 13 | replicaCount: 1 14 | auth: 15 | rbac: 16 | enabled: true 17 | rootPassword: myrootpass 18 | components: {} 19 | config: 20 | etcd: 21 | auth: 22 | enabled: true 23 | userName: root 24 | password: myrootpass 25 | -------------------------------------------------------------------------------- /config/samples/milvus_external_dependencies.yaml: -------------------------------------------------------------------------------- 1 | # This sample is used to deploy milvus with external dependencies 2 | # change the to match your environment 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | config: 11 | etcd: 12 | rootPath: my-release 13 | msgChannel: 14 | chanNamePrefix: 15 | cluster: my-release 16 | minio: 17 | bucketName: 18 | # config the prefix of the bucket milvus will use 19 | rootPath: milvus/my-release 20 | dependencies: 21 | etcd: 22 | external: true 23 | endpoints: ["", "", ""] 24 | storage: 25 | external: true 26 | endpoint: "" 27 | secretRef: "" 28 | # if you want to use s3 check ./milvus_s3.yaml 29 | type: MinIO 30 | -------------------------------------------------------------------------------- /config/samples/milvus_external_minio_ssl.yaml: -------------------------------------------------------------------------------- 1 | # Milvus External MinIO SSL Configuration Sample 2 | # This is a minimal working example for connecting Milvus to external MinIO with SSL 3 | --- 4 | # MinIO Credentials Secret (Required) 5 | apiVersion: v1 6 | kind: Secret 7 | metadata: 8 | name: minio-credentials 9 | namespace: milvus # adjust to your namespace 10 | type: Opaque 11 | data: 12 | accesskey: bWluaW8= # base64 encoded "minio" - replace with your MinIO access key 13 | secretkey: bWluaW8xMjM= # base64 encoded "minio123" - replace with your MinIO secret key 14 | 15 | --- 16 | # MinIO CA Certificate (Required for SSL) 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | name: minio-ca-cert 21 | namespace: milvus # adjust to your namespace 22 | data: 23 | ca.crt: | 24 | -----BEGIN CERTIFICATE----- 25 | # Replace this with your actual MinIO CA certificate content 26 | # You can get this from your MinIO server's certificate 27 | -----END CERTIFICATE----- 28 | 29 | --- 30 | # Milvus Cluster with External MinIO SSL 31 | apiVersion: milvus.io/v1beta1 32 | kind: Milvus 33 | metadata: 34 | name: my-milvus 35 | namespace: milvus # adjust to your namespace 36 | labels: 37 | app: milvus 38 | spec: 39 | mode: cluster 40 | 41 | # Dependencies configuration - used by operator for validation and connection testing 42 | dependencies: 43 | storage: 44 | type: MinIO 45 | external: true 46 | endpoint: minio.minio.svc.cluster.local:443 # adjust to your MinIO endpoint 47 | secretRef: minio-credentials 48 | ssl: 49 | enabled: true 50 | caCertificateRef: minio-ca-cert 51 | insecureSkipVerify: false # set to true only for testing 52 | 53 | # Milvus configuration - directly passed to Milvus components 54 | config: 55 | common: 56 | storageType: remote 57 | minio: 58 | useSSL: true # Required: enable SSL for Milvus components 59 | bucketName: milvus-bucket # Optional: specify bucket name (default: a-bucket) 60 | rootPath: files # Optional: specify root path for data storage 61 | ssl: 62 | tlsCACert: /etc/ssl/certs/minio-ca.crt # Required: path to CA certificate in container 63 | 64 | # Volume mounts for SSL certificate (Required) 65 | components: 66 | volumeMounts: 67 | - mountPath: /etc/ssl/certs/minio-ca.crt 68 | name: minio-ca-cert 69 | readOnly: true 70 | subPath: ca.crt 71 | volumes: 72 | - configMap: 73 | name: minio-ca-cert 74 | name: minio-ca-cert 75 | -------------------------------------------------------------------------------- /config/samples/milvus_gcs.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with GCS as its object storage. 2 | # change the to match your environment 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | config: 11 | minio: 12 | cloudProvider: gcp 13 | bucketName: 14 | rootPath: milvus/my-release 15 | useSSL: true 16 | dependencies: 17 | etcd: 18 | inCluster: 19 | values: 20 | replicaCount: 1 21 | deletionPolicy: Delete 22 | pvcDeletion: true 23 | storage: 24 | external: true 25 | type: S3 26 | endpoint: storage.googleapis.com:443 27 | secretRef: "my-release-s3-secret" 28 | --- 29 | apiVersion: v1 30 | kind: Secret 31 | metadata: 32 | name: my-release-s3-secret 33 | type: Opaque 34 | stringData: 35 | accesskey: 36 | secretkey: 37 | -------------------------------------------------------------------------------- /config/samples/milvus_gcs_iam.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with GCS as its object storage 2 | # and access GCS with AssumeRole. 3 | 4 | # change the to match your environment 5 | apiVersion: milvus.io/v1beta1 6 | kind: Milvus 7 | metadata: 8 | name: my-release 9 | labels: 10 | app: milvus 11 | spec: 12 | components: 13 | serviceAccountName: my-release-sa 14 | config: 15 | minio: 16 | cloudProvider: gcp 17 | bucketName: 18 | rootPath: milvus/my-release 19 | useSSL: true 20 | useIAM: true 21 | dependencies: 22 | storage: 23 | external: true 24 | type: S3 25 | # Note: you must use regional endpoint here, otherwise the minio client that milvus uses will fail to connect 26 | endpoint: storage.googleapis.com:443 27 | --- 28 | apiVersion: v1 29 | kind: ServiceAccount 30 | metadata: 31 | name: my-release-sa 32 | # gcp-service-account in the form of: @.iam.gserviceaccount.com 33 | iam.gke.io/gcp-service-account: 34 | -------------------------------------------------------------------------------- /config/samples/milvus_kafka.yaml: -------------------------------------------------------------------------------- 1 | # This is an example of Milvus deployment with Kafka as the message stream. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | config: 10 | kafka: 11 | # securityProtocol supports: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL 12 | securityProtocol: PLAINTEXT 13 | # saslMechanisms supports: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512 14 | saslMechanisms: PLAIN 15 | saslUsername: "" 16 | saslPassword: "" 17 | dependencies: 18 | msgStreamType: kafka 19 | kafka: 20 | inCluster: 21 | deletionPolicy: Delete 22 | pvcDeletion: true 23 | 24 | -------------------------------------------------------------------------------- /config/samples/milvus_metric_labels.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus with metrics labels. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | components: 10 | metricLabels: 11 | test_label1: test_value1 12 | test_label2: test_value2 13 | dependencies: 14 | etcd: 15 | inCluster: 16 | values: 17 | replicaCount: 1 18 | storage: 19 | inCluster: 20 | values: 21 | mode: standalone 22 | resources: 23 | requests: -------------------------------------------------------------------------------- /config/samples/milvus_minimum.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a milvus with minimum cost of resources. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | dependencies: 10 | etcd: 11 | inCluster: 12 | values: 13 | replicaCount: 1 14 | storage: 15 | inCluster: 16 | values: 17 | mode: standalone 18 | resources: 19 | requests: 20 | memory: 100Mi 21 | -------------------------------------------------------------------------------- /config/samples/milvus_natsmq.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a standalone milvus with rocksmq. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | # for now natsmq only support standalone mode 10 | mode: standalone 11 | dependencies: 12 | msgStreamType: natsmq 13 | natsmq: 14 | persistence: 15 | enabled: true 16 | -------------------------------------------------------------------------------- /config/samples/milvus_pulsar_v2.yaml: -------------------------------------------------------------------------------- 1 | # This is an example of Milvus deployment with Pulsar v3 as the message stream. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | dependencies: 10 | msgStreamType: pulsar 11 | pulsar: 12 | inCluster: 13 | chartVersion: pulsar-v2 14 | deletionPolicy: Delete 15 | pvcDeletion: true 16 | -------------------------------------------------------------------------------- /config/samples/milvus_pulsar_with_authn_jwt_token.yaml: -------------------------------------------------------------------------------- 1 | # This is an example of Milvus deployment with Pulsar with token authentication. 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: my-release-pulsar-token-symmetric-key 6 | type: Opaque 7 | stringData: 8 | # the root SECRETKEY used for signing jwt token for users 9 | SECRETKEY: my-pulsar-secret-key-example-change-it-to-your-own!! 10 | --- 11 | apiVersion: v1 12 | kind: Secret 13 | metadata: 14 | name: my-release-pulsar-token-milvus 15 | type: Opaque 16 | stringData: 17 | # signed to user: milvus with SECRETKEY 18 | TOKEN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtaWx2dXMifQ.2ciEzP9-vuwO6oI-4WfnYA1UqI5oXz7uOLJpOBrrhYo 19 | --- 20 | apiVersion: v1 21 | kind: Secret 22 | metadata: 23 | name: my-release-pulsar-token-pulsar-proxy 24 | type: Opaque 25 | stringData: 26 | # signed to user: pulsar-proxy with SECRETKEY 27 | TOKEN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJwdWxzYXItcHJveHkifQ.OgKpFomaZVIoMFl2GmgYED48RaDcFzhqe5Td_v8JNhU 28 | --- 29 | apiVersion: milvus.io/v1beta1 30 | kind: Milvus 31 | metadata: 32 | name: my-release 33 | labels: 34 | app: milvus 35 | spec: 36 | config: 37 | pulsar: 38 | authPlugin: token 39 | authParams: file:/milvus/pulsar/token 40 | component: 41 | volumes: 42 | - name: pulsar-token 43 | secret: 44 | secretName: my-release-pulsar-token-milvus 45 | items: 46 | - key: TOKEN 47 | path: token 48 | volumeMounts: 49 | - name: pulsar-token 50 | mountPath: /milvus/pulsar 51 | dependencies: 52 | msgStreamType: pulsar 53 | pulsar: 54 | inCluster: 55 | values: 56 | auth: 57 | authentication: 58 | enabled: true 59 | provider: "jwt" 60 | jwt: 61 | usingSecretKey: true 62 | authorization: 63 | enabled: true 64 | superUsers: 65 | # broker to broker communication 66 | broker: "milvus" 67 | # proxy to broker communication 68 | proxy: "pulsar-proxy" 69 | # pulsar-admin client to broker/proxy communication 70 | client: "" 71 | -------------------------------------------------------------------------------- /config/samples/milvus_resource.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to configure a milvus's cpu and memory resources. 2 | 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | components: 11 | resources: 12 | limits: 13 | cpu: '4' 14 | memory: 8Gi 15 | requests: 16 | cpu: '1' 17 | memory: 2Gi 18 | config: {} 19 | dependencies: {} -------------------------------------------------------------------------------- /config/samples/milvus_rocksmq.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a standalone milvus with rocksmq. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | labels: 7 | app: milvus 8 | spec: 9 | # rocksmq only support standalone mode 10 | mode: standalone 11 | dependencies: 12 | msgStreamType: rocksmq 13 | rocksmq: 14 | persistence: 15 | enabled: true 16 | -------------------------------------------------------------------------------- /config/samples/milvus_rolling_update.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to deploy a standalone milvus in milvus-operator's default configurations. 2 | apiVersion: milvus.io/v1beta1 3 | kind: Milvus 4 | metadata: 5 | name: my-release 6 | spec: 7 | components: 8 | enableRollingUpdate: true 9 | imageUpdateMode: rollingUpgrade # rollingUpgrade / rollingDowngrade / all 10 | -------------------------------------------------------------------------------- /config/samples/milvus_s3.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with AWS S3 as its object storage. 2 | # # change the to match your environment 3 | apiVersion: milvus.io/v1beta1 4 | kind: Milvus 5 | metadata: 6 | name: my-release 7 | labels: 8 | app: milvus 9 | spec: 10 | config: 11 | minio: 12 | bucketName: 13 | # config the prefix of the bucket milvus will use 14 | rootPath: milvus/my-release 15 | useSSL: true 16 | dependencies: 17 | storage: 18 | external: true 19 | type: S3 20 | endpoint: s3.amazonaws.com:443 21 | secretRef: "my-release-s3-secret" 22 | --- 23 | apiVersion: v1 24 | kind: Secret 25 | metadata: 26 | name: my-release-s3-secret 27 | type: Opaque 28 | stringData: 29 | accesskey: 30 | secretkey: 31 | -------------------------------------------------------------------------------- /config/samples/milvus_s3_iam.yaml: -------------------------------------------------------------------------------- 1 | # This sample file is used to deploy Milvus with AWS S3 as its object storage 2 | # and access AWS S3 with AssumeRole. 3 | 4 | # change the to match your environment 5 | apiVersion: milvus.io/v1beta1 6 | kind: Milvus 7 | metadata: 8 | name: my-release 9 | labels: 10 | app: milvus 11 | spec: 12 | components: 13 | serviceAccountName: my-release-sa 14 | image: milvusdb/milvus-dev:master-latest 15 | config: 16 | minio: 17 | bucketName: 18 | rootPath: milvus/my-release 19 | useSSL: true 20 | useIAM: true 21 | dependencies: 22 | storage: 23 | external: true 24 | type: S3 25 | # Note: you must use regional endpoint here, otherwise the minio client that milvus uses will fail to connect 26 | endpoint: s3..amazonaws.com:443 27 | --- 28 | apiVersion: v1 29 | kind: ServiceAccount 30 | metadata: 31 | name: my-release-sa 32 | annotations: 33 | eks.amazonaws.com/role-arn: 34 | -------------------------------------------------------------------------------- /config/samples/milvusupgrade.yaml: -------------------------------------------------------------------------------- 1 | # This is a sample to upgrade a milvus from v2.1.4 to v2.2.0. 2 | apiVersion: milvus.io/v1beta1 3 | kind: MilvusUpgrade 4 | metadata: 5 | name: my-release-upgrade 6 | spec: 7 | milvus: 8 | namespace: default 9 | name: my-release 10 | sourceVersion: "v2.1.4" 11 | targetVersion: "v2.2.0" 12 | # below are some omit default values: 13 | # targetImage: "milvusdb/milvus:v2.2.0" 14 | # toolImage: "milvusdb/meta-migration:v2.2.0" 15 | # operation: upgrade 16 | # rollbackIfFailed: true 17 | # backupPVC: "" 18 | # maxRetry: 3 19 | -------------------------------------------------------------------------------- /config/samples/run_as_non_root.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mc-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: mc-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | components: 16 | runAsNonRoot: true 17 | volumes: 18 | - emptyDir: {} 19 | name: data 20 | volumeMounts: 21 | - mountPath: /milvus/data 22 | name: data 23 | config: 24 | localStorage: 25 | path: /milvus/data 26 | -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting vars. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | 24 | varReference: 25 | - path: metadata/annotations 26 | -------------------------------------------------------------------------------- /config/webhook/manifests.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: MutatingWebhookConfiguration 4 | metadata: 5 | name: mutating-webhook-configuration 6 | webhooks: 7 | - admissionReviewVersions: 8 | - v1 9 | clientConfig: 10 | service: 11 | name: webhook-service 12 | namespace: system 13 | path: /mutate-milvus-io-v1beta1-milvus 14 | failurePolicy: Fail 15 | name: mmilvus.kb.io 16 | rules: 17 | - apiGroups: 18 | - milvus.io 19 | apiVersions: 20 | - v1beta1 21 | operations: 22 | - CREATE 23 | - UPDATE 24 | resources: 25 | - milvuses 26 | sideEffects: None 27 | - admissionReviewVersions: 28 | - v1 29 | clientConfig: 30 | service: 31 | name: webhook-service 32 | namespace: system 33 | path: /mutate-milvus-io-v1beta1-milvusupgrade 34 | failurePolicy: Fail 35 | name: mmilvusupgrade.kb.io 36 | rules: 37 | - apiGroups: 38 | - milvus.io 39 | apiVersions: 40 | - v1beta1 41 | operations: 42 | - CREATE 43 | - UPDATE 44 | resources: 45 | - milvusupgrades 46 | sideEffects: None 47 | --- 48 | apiVersion: admissionregistration.k8s.io/v1 49 | kind: ValidatingWebhookConfiguration 50 | metadata: 51 | name: validating-webhook-configuration 52 | webhooks: 53 | - admissionReviewVersions: 54 | - v1 55 | clientConfig: 56 | service: 57 | name: webhook-service 58 | namespace: system 59 | path: /validate-milvus-io-v1beta1-milvus 60 | failurePolicy: Fail 61 | name: vmilvus.kb.io 62 | rules: 63 | - apiGroups: 64 | - milvus.io 65 | apiVersions: 66 | - v1beta1 67 | operations: 68 | - CREATE 69 | - UPDATE 70 | resources: 71 | - milvuses 72 | sideEffects: None 73 | - admissionReviewVersions: 74 | - v1 75 | clientConfig: 76 | service: 77 | name: webhook-service 78 | namespace: system 79 | path: /validate-milvus-io-v1beta1-milvusupgrade 80 | failurePolicy: Fail 81 | name: vmilvusupgrade.kb.io 82 | rules: 83 | - apiGroups: 84 | - milvus.io 85 | apiVersions: 86 | - v1beta1 87 | operations: 88 | - CREATE 89 | - UPDATE 90 | resources: 91 | - milvusupgrades 92 | sideEffects: None 93 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /ct.yaml: -------------------------------------------------------------------------------- 1 | remote: origin 2 | chart-dirs: 3 | - charts 4 | helm-extra-args: --timeout 900s -------------------------------------------------------------------------------- /docs/CRD/(deprecated)milvus-cluster.md: -------------------------------------------------------------------------------- 1 | # Note 2 | 3 | The `MilvusCluster` CRD is deprecated. Please use `Milvus` CRD instead. 4 | -------------------------------------------------------------------------------- /docs/administration/allocate-resources.md: -------------------------------------------------------------------------------- 1 | # Allocate Resources with Milvus Operator 2 | 3 | We can allocate resources for a single component or for all components in a Milvus cluster. 4 | 5 | ## Example 6 | 7 | The following example allocates: 8 | - 1 CPU and 2 GiB memory for the mixCoord 9 | - 2 CPUs and 4 GiB memory for the proxy 10 | - 4 CPUs and 8 GiB memory for all other components (including the queryNodes, indexNodes and dataNodes) 11 | 12 | ```yaml 13 | apiVersion: milvus.io/v1beta1 14 | kind: Milvus 15 | metadata: 16 | name: my-release 17 | labels: 18 | app: milvus 19 | spec: 20 | # Omit other fields ... 21 | mode: cluster 22 | components: 23 | resources: 24 | limits: 25 | cpu: '4' 26 | memory: 8Gi 27 | mixCoord: 28 | resources: 29 | limits: 30 | cpu: '1' 31 | memory: 2Gi 32 | proxy: 33 | serviceType: LoadBalancer 34 | resources: 35 | limits: 36 | cpu: '2' 37 | memory: 4Gi 38 | ``` 39 | 40 | # More samples for different scale Milvus 41 | 42 | check samples in https://github.com/zilliztech/milvus-operator/tree/main/config/samples 43 | 44 | # How much resources should I allocate for Milvus 45 | 46 | Check out sizing tool in https://milvus.io/tools/sizing -------------------------------------------------------------------------------- /docs/administration/monitor-and-alert.md: -------------------------------------------------------------------------------- 1 | # Monitor and Alert 2 | 3 | If you've installed Prometheus operator in your cluster, milvus-operator will enable the metrics service automatically. 4 | 5 | Check this article for more infomation: https://milvus.io/docs/monitor_overview.md -------------------------------------------------------------------------------- /docs/arch/arch.md: -------------------------------------------------------------------------------- 1 | # How it works 2 | 3 | ## Overall design 4 | 5 | The diagram shown below describes the overall design of the Milvus operator functionalities. 6 | 7 | ![overall design](../images/arch.jpg) 8 | 9 | A CR `MilvusCluster` is introduced to hold the whole component stack of the deploying Milvus cluster. The Milvus cluster owns all of the Milvus components itself as well as the possible related dependent services including 'etcd', 'minio' and 'pulsar'. The `MilvusCluster` controller takes charge of the reconciling process to make all the Milvus components and the related dependent service can be correctly created, updated and even deleted. 10 | 11 | Regarding the related dependenies required by running Milvus cluster, if the user has corresponding pre-deployed dependencies and is willing to use, these pre-deployed dependencies can be configured into the MilvusCluster CR instead of provisioning in-cluster dependencies by the operator itself. Choosing which way totally depends on the user's actual case. 12 | 13 | Whether using in-cluster or external dependencies, the status of dependencies determines whether Milvus is healthy. In order to get the overall status of Milvus cluster, Milvus Operator needs check all the status of dependencies. the status checker module in milvus operator doing check status of dependencies periodically, it use client library to do the actual request from operator pod to dependencies endpoints. 14 | 15 | -------------------------------------------------------------------------------- /docs/images/arch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zilliztech/milvus-operator/37fead15c5447bb31cc86a9d45d57e820f62e265/docs/images/arch.jpg -------------------------------------------------------------------------------- /docs/installation/kind-installation.md: -------------------------------------------------------------------------------- 1 | # Create a kind cluster 2 | 3 | > The Kind cluster is only for development/testing purpose. 4 | 5 | ## Prerequisites 6 | 7 | * [Docker](https://docs.docker.com/engine/install/) installed (Version: v19.03.12+) 8 | * [kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation) installed (Version: v0.8.1+). 9 | * [kubectl](https://kubernetes.io/docs/tasks/tools/) installed (Version: v1.19+) 10 | 11 | ## Prepare kind config 12 | Use the following command to create the kind configuration used for creating a kind cluster with multiple worker nodes: 13 | ```shell 14 | kind: Cluster 15 | apiVersion: kind.x-k8s.io/v1alpha4 16 | nodes: 17 | - role: control-plane 18 | - role: worker 19 | - role: worker 20 | - role: worker 21 | ``` 22 | 23 | ## Create the kind cluster 24 | 25 | Execute command: 26 | 27 | ```shell script 28 | kind create cluster --name myk8s --config kind.yaml 29 | ``` 30 | 31 | ## Check the cluster info 32 | Check cluster info by 33 | 34 | ```shell script 35 | kubectl cluster-info 36 | ``` 37 | 38 | Output: 39 | 40 | ```log 41 | Kubernetes master is running at https://127.0.0.1:39821 42 | KubeDNS is running at https://127.0.0.1:39821/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy 43 | 44 | To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. 45 | ``` -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /hack/update-codegen.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. 8 | GOPATH=$(go env GOPATH) 9 | 10 | # we use specific "client,lister,informer" instead of "all", for kubebuilder will generate deepcopy 11 | ${SCRIPT_ROOT}/hack/generate-groups.sh client,lister,informer \ 12 | github.com/zilliztech/milvus-operator/pkg/client \ 13 | github.com/zilliztech/milvus-operator/apis \ 14 | "milvus.io:v1beta1" \ 15 | --go-header-file "${SCRIPT_ROOT}/hack/boilerplate.go.txt" 16 | -------------------------------------------------------------------------------- /local.Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # # Use distroless as minimal base image to package the manager binary 3 | # # Refer to https://github.com/GoogleContainerTools/distroless for more details 4 | FROM gcr.io/distroless/static:nonroot 5 | WORKDIR / 6 | ADD out/ / 7 | 8 | USER 65532:65532 9 | 10 | ENTRYPOINT ["/manager"] 11 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated clientset. 19 | package versioned 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated fake clientset. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/fake/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | runtime "k8s.io/apimachinery/pkg/runtime" 23 | schema "k8s.io/apimachinery/pkg/runtime/schema" 24 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 25 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 26 | 27 | milvusv1beta1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 28 | ) 29 | 30 | var scheme = runtime.NewScheme() 31 | var codecs = serializer.NewCodecFactory(scheme) 32 | 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | milvusv1beta1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package contains the scheme of the automatically generated clientset. 19 | package scheme 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/scheme/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package scheme 19 | 20 | import ( 21 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | runtime "k8s.io/apimachinery/pkg/runtime" 23 | schema "k8s.io/apimachinery/pkg/runtime/schema" 24 | serializer "k8s.io/apimachinery/pkg/runtime/serializer" 25 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 26 | 27 | milvusv1beta1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 28 | ) 29 | 30 | var Scheme = runtime.NewScheme() 31 | var Codecs = serializer.NewCodecFactory(Scheme) 32 | var ParameterCodec = runtime.NewParameterCodec(Scheme) 33 | var localSchemeBuilder = runtime.SchemeBuilder{ 34 | milvusv1beta1.AddToScheme, 35 | } 36 | 37 | // AddToScheme adds all types of this clientset into the given scheme. This allows composition 38 | // of clientsets, like in: 39 | // 40 | // import ( 41 | // "k8s.io/client-go/kubernetes" 42 | // clientsetscheme "k8s.io/client-go/kubernetes/scheme" 43 | // aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" 44 | // ) 45 | // 46 | // kclientset, _ := kubernetes.NewForConfig(c) 47 | // _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) 48 | // 49 | // After this, RawExtensions in Kubernetes types will serialize kube-aggregator types 50 | // correctly. 51 | var AddToScheme = localSchemeBuilder.AddToScheme 52 | 53 | func init() { 54 | v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) 55 | utilruntime.Must(AddToScheme(Scheme)) 56 | } 57 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/milvus.io/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // This package has the automatically generated typed clients. 19 | package v1beta1 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/milvus.io/v1beta1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | // Package fake has the automatically generated clients. 19 | package fake 20 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/milvus.io/v1beta1/fake/fake_milvus.io_client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package fake 19 | 20 | import ( 21 | rest "k8s.io/client-go/rest" 22 | testing "k8s.io/client-go/testing" 23 | 24 | v1beta1 "github.com/zilliztech/milvus-operator/pkg/client/clientset/versioned/typed/milvus.io/v1beta1" 25 | ) 26 | 27 | type FakeMilvusV1beta1 struct { 28 | *testing.Fake 29 | } 30 | 31 | func (c *FakeMilvusV1beta1) Milvuses(namespace string) v1beta1.MilvusInterface { 32 | return &FakeMilvuses{c, namespace} 33 | } 34 | 35 | // RESTClient returns a RESTClient that is used to communicate 36 | // with API server by this client implementation. 37 | func (c *FakeMilvusV1beta1) RESTClient() rest.Interface { 38 | var ret *rest.RESTClient 39 | return ret 40 | } 41 | -------------------------------------------------------------------------------- /pkg/client/clientset/versioned/typed/milvus.io/v1beta1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by client-gen. DO NOT EDIT. 17 | 18 | package v1beta1 19 | 20 | type MilvusExpansion interface{} 21 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/generic.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package externalversions 19 | 20 | import ( 21 | "fmt" 22 | 23 | schema "k8s.io/apimachinery/pkg/runtime/schema" 24 | cache "k8s.io/client-go/tools/cache" 25 | 26 | v1beta1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 27 | ) 28 | 29 | // GenericInformer is type of SharedIndexInformer which will locate and delegate to other 30 | // sharedInformers based on type 31 | type GenericInformer interface { 32 | Informer() cache.SharedIndexInformer 33 | Lister() cache.GenericLister 34 | } 35 | 36 | type genericInformer struct { 37 | informer cache.SharedIndexInformer 38 | resource schema.GroupResource 39 | } 40 | 41 | // Informer returns the SharedIndexInformer. 42 | func (f *genericInformer) Informer() cache.SharedIndexInformer { 43 | return f.informer 44 | } 45 | 46 | // Lister returns the GenericLister. 47 | func (f *genericInformer) Lister() cache.GenericLister { 48 | return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) 49 | } 50 | 51 | // ForResource gives generic access to a shared informer of the matching type 52 | // TODO extend this to unknown resources with a client pool 53 | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { 54 | switch resource { 55 | // Group=milvus.io, Version=v1beta1 56 | case v1beta1.SchemeGroupVersion.WithResource("milvuses"): 57 | return &genericInformer{resource: resource.GroupResource(), informer: f.Milvus().V1beta1().Milvuses().Informer()}, nil 58 | 59 | } 60 | 61 | return nil, fmt.Errorf("no informer found for %v", resource) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package internalinterfaces 19 | 20 | import ( 21 | time "time" 22 | 23 | v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | cache "k8s.io/client-go/tools/cache" 26 | 27 | versioned "github.com/zilliztech/milvus-operator/pkg/client/clientset/versioned" 28 | ) 29 | 30 | // NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. 31 | type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer 32 | 33 | // SharedInformerFactory a small interface to allow for adding an informer without an import cycle 34 | type SharedInformerFactory interface { 35 | Start(stopCh <-chan struct{}) 36 | InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer 37 | } 38 | 39 | // TweakListOptionsFunc is a function that transforms a v1.ListOptions. 40 | type TweakListOptionsFunc func(*v1.ListOptions) 41 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/milvus.io/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package milvus 19 | 20 | import ( 21 | internalinterfaces "github.com/zilliztech/milvus-operator/pkg/client/informers/externalversions/internalinterfaces" 22 | v1beta1 "github.com/zilliztech/milvus-operator/pkg/client/informers/externalversions/milvus.io/v1beta1" 23 | ) 24 | 25 | // Interface provides access to each of this group's versions. 26 | type Interface interface { 27 | // V1beta1 provides access to shared informers for resources in V1beta1. 28 | V1beta1() v1beta1.Interface 29 | } 30 | 31 | type group struct { 32 | factory internalinterfaces.SharedInformerFactory 33 | namespace string 34 | tweakListOptions internalinterfaces.TweakListOptionsFunc 35 | } 36 | 37 | // New returns a new Interface. 38 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 39 | return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 40 | } 41 | 42 | // V1beta1 returns a new v1beta1.Interface. 43 | func (g *group) V1beta1() v1beta1.Interface { 44 | return v1beta1.New(g.factory, g.namespace, g.tweakListOptions) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/client/informers/externalversions/milvus.io/v1beta1/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by informer-gen. DO NOT EDIT. 17 | 18 | package v1beta1 19 | 20 | import ( 21 | internalinterfaces "github.com/zilliztech/milvus-operator/pkg/client/informers/externalversions/internalinterfaces" 22 | ) 23 | 24 | // Interface provides access to all the informers in this group version. 25 | type Interface interface { 26 | // Milvuses returns a MilvusInformer. 27 | Milvuses() MilvusInformer 28 | } 29 | 30 | type version struct { 31 | factory internalinterfaces.SharedInformerFactory 32 | namespace string 33 | tweakListOptions internalinterfaces.TweakListOptionsFunc 34 | } 35 | 36 | // New returns a new Interface. 37 | func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { 38 | return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} 39 | } 40 | 41 | // Milvuses returns a MilvusInformer. 42 | func (v *version) Milvuses() MilvusInformer { 43 | return &milvusInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} 44 | } 45 | -------------------------------------------------------------------------------- /pkg/client/listers/milvus.io/v1beta1/expansion_generated.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | // Code generated by lister-gen. DO NOT EDIT. 17 | 18 | package v1beta1 19 | 20 | // MilvusListerExpansion allows custom methods to be added to 21 | // MilvusLister. 22 | type MilvusListerExpansion interface{} 23 | 24 | // MilvusNamespaceListerExpansion allows custom methods to be added to 25 | // MilvusNamespaceLister. 26 | type MilvusNamespaceListerExpansion interface{} 27 | -------------------------------------------------------------------------------- /pkg/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | const ( 8 | // DefaultMilvusVersion is the default version used when a new Milvus deployment is created. 9 | DefaultMilvusVersion = "v2.5.10" 10 | // DefaultMilvusBaseImage is the default Miluvs container image. 11 | DefaultMilvusBaseImage = "milvusdb/milvus" 12 | // DefaultMilvusImage is the default container image:version. 13 | DefaultMilvusImage = DefaultMilvusBaseImage + ":" + DefaultMilvusVersion 14 | milvusConfigTpl = "milvus.yaml.tmpl" 15 | milvusClusterConfigTpl = "milvus-cluster.yaml.tmpl" 16 | migrationConfigTpl = "migration.yaml.tmpl" 17 | ) 18 | 19 | const ( 20 | TemplateRelativeDir = "config/assets/templates" 21 | ChartDir = "config/assets/charts" 22 | ProviderName = "milvus-operator" 23 | ) 24 | 25 | var ( 26 | defaultConfig *Config 27 | // set by run flag in main 28 | OperatorNamespace = "milvus-operator" 29 | OperatorName = "milvus-operator" 30 | // param related to performance 31 | MaxConcurrentReconcile = 10 32 | MaxConcurrentHealthCheck = 10 33 | SyncIntervalSec = 600 34 | ) 35 | 36 | func Init(workDir string) error { 37 | c, err := NewConfig(workDir) 38 | if err != nil { 39 | return err 40 | } 41 | defaultConfig = c 42 | if os.Getenv("DEBUG") == "true" { 43 | defaultConfig.debugMode = true 44 | } 45 | 46 | return nil 47 | } 48 | 49 | func IsDebug() bool { 50 | return defaultConfig.debugMode 51 | } 52 | 53 | func GetMilvusConfigTemplate() string { 54 | return defaultConfig.GetTemplate(milvusConfigTpl) 55 | } 56 | 57 | func GetMilvusClusterConfigTemplate() string { 58 | return defaultConfig.GetTemplate(milvusClusterConfigTpl) 59 | } 60 | 61 | func GetMigrationConfigTemplate() string { 62 | return defaultConfig.GetTemplate(migrationConfigTpl) 63 | } 64 | 65 | type Config struct { 66 | debugMode bool 67 | templates map[string]string 68 | } 69 | 70 | func NewConfig(workDir string) (*Config, error) { 71 | config := &Config{ 72 | templates: make(map[string]string), 73 | } 74 | 75 | templateDir := workDir + TemplateRelativeDir 76 | 77 | tmpls, err := os.ReadDir(templateDir) 78 | if err != nil { 79 | return nil, err 80 | } 81 | for _, tmpl := range tmpls { 82 | data, err := os.ReadFile(templateDir + "/" + tmpl.Name()) 83 | if err != nil { 84 | return nil, err 85 | } 86 | 87 | config.templates[tmpl.Name()] = string(data) 88 | } 89 | 90 | return config, nil 91 | } 92 | 93 | func (c Config) GetTemplate(name string) string { 94 | return c.templates[name] 95 | } 96 | -------------------------------------------------------------------------------- /pkg/config/config_test.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | 9 | "github.com/zilliztech/milvus-operator/pkg/util" 10 | ) 11 | 12 | func TestInit_NewConfigFailed(t *testing.T) { 13 | workDir := "/a-bad-path/a-bad-path" 14 | err := Init(workDir) 15 | assert.Error(t, err) 16 | } 17 | 18 | func TestInit_Success(t *testing.T) { 19 | workDir := util.GetGitRepoRootDir() 20 | err := Init(workDir) 21 | assert.NoError(t, err) 22 | assert.Equal(t, false, defaultConfig.debugMode) 23 | } 24 | 25 | func TestInit_Debug(t *testing.T) { 26 | os.Setenv("DEBUG", "true") 27 | workDir := util.GetGitRepoRootDir() 28 | err := Init(workDir) 29 | assert.NoError(t, err) 30 | assert.Equal(t, true, defaultConfig.debugMode) 31 | assert.True(t, IsDebug()) 32 | } 33 | 34 | func TestConfig_GetTemplate(t *testing.T) { 35 | defaultConfig = &Config{ 36 | templates: map[string]string{ 37 | "key": "value", 38 | }, 39 | } 40 | 41 | assert.Equal(t, "value", defaultConfig.GetTemplate("key")) 42 | } 43 | func TestGetMilvusConfigTemplate(t *testing.T) { 44 | defaultConfig = &Config{ 45 | templates: map[string]string{ 46 | milvusConfigTpl: "value", 47 | milvusClusterConfigTpl: "value2", 48 | }, 49 | } 50 | assert.Equal(t, "value2", GetMilvusClusterConfigTemplate()) 51 | assert.Equal(t, "value", GetMilvusConfigTemplate()) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/controllers/common_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "go.uber.org/mock/gomock" 8 | "helm.sh/helm/v3/pkg/cli" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | "k8s.io/apimachinery/pkg/runtime" 11 | "k8s.io/client-go/rest" 12 | ctrlRuntime "sigs.k8s.io/controller-runtime" 13 | 14 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 15 | "github.com/zilliztech/milvus-operator/pkg/config" 16 | "github.com/zilliztech/milvus-operator/pkg/helm" 17 | "github.com/zilliztech/milvus-operator/pkg/util" 18 | ) 19 | 20 | type clusterTestEnv struct { 21 | MockClient *MockK8sClient 22 | Ctrl *gomock.Controller 23 | Reconciler *MilvusReconciler 24 | Inst v1beta1.Milvus 25 | ctx context.Context 26 | } 27 | 28 | func (m *clusterTestEnv) checkMocks() { 29 | m.Ctrl.Finish() 30 | } 31 | 32 | func newTestEnv(t *testing.T) *clusterTestEnv { 33 | config.Init(util.GetGitRepoRootDir()) 34 | 35 | ctrl := gomock.NewController(t) 36 | reconciler := newMilvusReconcilerForTest(ctrl) 37 | mockClient := reconciler.Client.(*MockK8sClient) 38 | 39 | inst := v1beta1.Milvus{ 40 | ObjectMeta: metav1.ObjectMeta{ 41 | Namespace: "ns", 42 | Name: "mc", 43 | }, 44 | } 45 | inst.Default() 46 | return &clusterTestEnv{ 47 | MockClient: mockClient, 48 | Ctrl: ctrl, 49 | Reconciler: reconciler, 50 | Inst: inst, 51 | ctx: context.Background(), 52 | } 53 | } 54 | 55 | func newMilvusReconcilerForTest(ctrl *gomock.Controller) *MilvusReconciler { 56 | mockClient := NewMockK8sClient(ctrl) 57 | 58 | logger := ctrlRuntime.Log.WithName("test") 59 | scheme := runtime.NewScheme() 60 | v1beta1.AddToScheme(scheme) 61 | helmSetting := cli.New() 62 | 63 | mockManager := NewMockManager(ctrl) 64 | restConfig := &rest.Config{} 65 | mockManager.EXPECT().GetConfig().Return(restConfig).AnyTimes() 66 | mockManager.EXPECT().GetClient().Return(mockClient).AnyTimes() 67 | 68 | helmClient := helm.NewMockClient(ctrl) 69 | helmClient.EXPECT().ReleaseExist(gomock.Any(), gomock.Any()).Return(false, nil).AnyTimes() 70 | helm.SetDefaultClient(helmClient) 71 | helmReconciler := MustNewLocalHelmReconciler(helmSetting, logger, mockManager) 72 | 73 | r := MilvusReconciler{ 74 | Client: mockClient, 75 | logger: logger, 76 | Scheme: scheme, 77 | helmReconciler: helmReconciler, 78 | } 79 | return &r 80 | } 81 | 82 | func TestCommonTestDummy(t *testing.T) { 83 | } 84 | -------------------------------------------------------------------------------- /pkg/controllers/endpoint_check_cache_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | 8 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 9 | ) 10 | 11 | func TestEndpointCheckCache(t *testing.T) { 12 | t.Run("empty ignored", func(t *testing.T) { 13 | key := []string{} 14 | _, found := endpointCheckCache.Get(key) 15 | assert.False(t, found) 16 | cond := &v1beta1.MilvusCondition{Reason: "OK"} 17 | endpointCheckCache.Set(key, cond) 18 | _, found = endpointCheckCache.Get(key) 19 | assert.False(t, found) 20 | }) 21 | 22 | t.Run("set,get", func(t *testing.T) { 23 | key1 := []string{"a"} 24 | _, found := endpointCheckCache.Get(key1) 25 | assert.False(t, found) 26 | cond := &v1beta1.MilvusCondition{Reason: "OK"} 27 | endpointCheckCache.Set(key1, cond) 28 | ret, found := endpointCheckCache.Get(key1) 29 | assert.True(t, found) 30 | assert.Equal(t, cond, ret) 31 | }) 32 | 33 | t.Run("set,get array", func(t *testing.T) { 34 | key1 := []string{"a", "b", "c"} 35 | key2 := []string{"c", "a", "b"} 36 | _, found := endpointCheckCache.Get(key1) 37 | assert.False(t, found) 38 | cond := &v1beta1.MilvusCondition{Reason: "OK"} 39 | endpointCheckCache.Set(key1, cond) 40 | ret, found := endpointCheckCache.Get(key2) 41 | assert.True(t, found) 42 | assert.Equal(t, cond, ret) 43 | }) 44 | 45 | } 46 | -------------------------------------------------------------------------------- /pkg/controllers/external_interfaces.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | clientv3 "go.etcd.io/etcd/client/v3" 7 | "sigs.k8s.io/controller-runtime/pkg/client" 8 | ) 9 | 10 | //go:generate mockgen -package=controllers -source=external_interfaces.go -destination=external_interfaces_mock.go 11 | 12 | // K8sClient for mock 13 | type K8sClient interface { 14 | client.Client 15 | } 16 | 17 | // K8sStatusClient for mock K8sClient.Status() 18 | type K8sStatusClient interface { 19 | client.SubResourceWriter 20 | } 21 | 22 | // EtcdClient for mock 23 | type EtcdClient interface { 24 | Get(ctx context.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) 25 | AlarmList(ctx context.Context) (*clientv3.AlarmResponse, error) 26 | Close() error 27 | } 28 | -------------------------------------------------------------------------------- /pkg/controllers/groups.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | "runtime/debug" 6 | "strings" 7 | "sync" 8 | 9 | "github.com/pkg/errors" 10 | logf "sigs.k8s.io/controller-runtime/pkg/log" 11 | 12 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 13 | "github.com/zilliztech/milvus-operator/pkg/config" 14 | ) 15 | 16 | var groupLog = logf.Log.WithName("group") 17 | 18 | type Group struct { 19 | wait sync.WaitGroup 20 | cancel context.CancelFunc 21 | 22 | // Collect all the errors 23 | errors []error 24 | locker *sync.Mutex 25 | } 26 | 27 | // NewGroup creates a new group. 28 | func NewGroup(ctx context.Context) (*Group, context.Context) { 29 | gtx, cancel := context.WithCancel(ctx) 30 | 31 | return &Group{ 32 | cancel: cancel, 33 | errors: make([]error, 0), 34 | locker: &sync.Mutex{}, 35 | }, gtx 36 | } 37 | 38 | // Go to run a func. 39 | func (g *Group) Go(f func() error) { 40 | g.wait.Add(1) 41 | 42 | go func() { 43 | defer g.wait.Done() 44 | if !config.IsDebug() { 45 | defer func() { 46 | if r := recover(); r != nil { 47 | stack := string(debug.Stack()) 48 | err := errors.Errorf("%s", r) 49 | groupLog.Error(err, "panic captured", "stack", stack) 50 | 51 | g.locker.Lock() 52 | g.errors = append(g.errors, err) 53 | g.locker.Unlock() 54 | } 55 | }() 56 | } 57 | 58 | // Run and handle error 59 | if err := f(); err != nil { 60 | g.locker.Lock() 61 | defer g.locker.Unlock() 62 | 63 | g.errors = append(g.errors, err) 64 | } 65 | }() 66 | } 67 | 68 | // Wait until all the go functions are returned 69 | // If errors occurred, they'll be combined with ":" and returned. 70 | func (g *Group) Wait() error { 71 | g.wait.Wait() 72 | 73 | defer func() { 74 | if g.cancel != nil { 75 | // Send signals to the downstream components 76 | g.cancel() 77 | } 78 | }() 79 | 80 | errTexts := make([]string, 0) 81 | for _, e := range g.errors { 82 | if errors.Is(e, ErrRequeue) { 83 | return e 84 | } 85 | errTexts = append(errTexts, e.Error()) 86 | } 87 | 88 | if len(errTexts) > 0 { 89 | return errors.Errorf("groups error: %s", strings.Join(errTexts, ";")) 90 | } 91 | 92 | return nil 93 | } 94 | 95 | func WarppedReconcileComponentFunc( 96 | f func(context.Context, v1beta1.Milvus, MilvusComponent) error, 97 | ctx context.Context, mc v1beta1.Milvus, c MilvusComponent) func() error { 98 | return func() error { 99 | return f(ctx, mc, c) 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /pkg/controllers/groups_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/assert" 10 | 11 | "github.com/zilliztech/milvus-operator/pkg/config" 12 | "github.com/zilliztech/milvus-operator/pkg/util" 13 | ) 14 | 15 | func TestGroup_Go_NoErr(t *testing.T) { 16 | config.Init(util.GetGitRepoRootDir()) 17 | ctx, cancel := context.WithCancel(context.Background()) 18 | defer cancel() 19 | g, gtx := NewGroup(ctx) 20 | g.Go(func() error { return nil }) 21 | g.Go(func() error { return nil }) 22 | g.Go(func() error { return nil }) 23 | 24 | err := g.Wait() 25 | assert.NoError(t, err) 26 | 27 | // ctx cancel 28 | wrapJobFunc := func(ctx context.Context) func() error { 29 | return func() error { 30 | select { 31 | case <-ctx.Done(): 32 | case <-time.After(time.Hour): 33 | } 34 | return nil 35 | } 36 | } 37 | g.Go(wrapJobFunc(gtx)) 38 | g.Go(wrapJobFunc(gtx)) 39 | g.Go(wrapJobFunc(gtx)) 40 | cancel() 41 | err = g.Wait() 42 | assert.NoError(t, err) 43 | } 44 | 45 | func TestGroup_Go_Err(t *testing.T) { 46 | config.Init(util.GetGitRepoRootDir()) 47 | ctx, cancel := context.WithCancel(context.Background()) 48 | defer cancel() 49 | g, _ := NewGroup(ctx) 50 | g.Go(func() error { return errors.New("mock") }) 51 | g.Go(func() error { return nil }) 52 | g.Go(func() error { return nil }) 53 | 54 | err := g.Wait() 55 | assert.Error(t, err) 56 | } 57 | 58 | func TestGroup_Go_Panic(t *testing.T) { 59 | config.Init(util.GetGitRepoRootDir()) 60 | ctx := context.Background() 61 | g, _ := NewGroup(ctx) 62 | g.Go(func() error { panic("mock") }) 63 | g.Go(func() error { return nil }) 64 | g.Go(func() error { return nil }) 65 | 66 | err := g.Wait() 67 | assert.Error(t, err) 68 | } 69 | -------------------------------------------------------------------------------- /pkg/controllers/k8s_default_values.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import corev1 "k8s.io/api/core/v1" 4 | 5 | func fillContainerDefaultValues(c *corev1.Container) { 6 | for i := range c.Ports { 7 | if c.Ports[i].Protocol == "" { 8 | c.Ports[i].Protocol = corev1.ProtocolTCP 9 | } 10 | } 11 | if c.ImagePullPolicy == "" { 12 | c.ImagePullPolicy = corev1.PullIfNotPresent 13 | } 14 | if c.TerminationMessagePath == "" { 15 | c.TerminationMessagePath = "/dev/termination-log" 16 | } 17 | if c.TerminationMessagePolicy == "" { 18 | c.TerminationMessagePolicy = corev1.TerminationMessageReadFile 19 | } 20 | } 21 | 22 | func fillConfigMapVolumeDefaultValues(v *corev1.Volume) { 23 | if v.ConfigMap == nil { 24 | return 25 | } 26 | if v.ConfigMap.DefaultMode == nil { 27 | v.ConfigMap.DefaultMode = int32Ptr(int(DefaultConfigMapMode)) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pkg/controllers/metrics.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/prometheus/client_golang/prometheus" 5 | versioncollector "github.com/prometheus/client_golang/prometheus/collectors/version" 6 | "github.com/prometheus/common/version" 7 | "sigs.k8s.io/controller-runtime/pkg/metrics" 8 | 9 | v1beta1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 10 | ) 11 | 12 | var ( 13 | milvusStatusCollector = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 14 | Subsystem: "milvus", 15 | Name: "status", 16 | Help: "Recording the changing status of each milvus", 17 | }, []string{"milvus_namespace", "milvus_name"}) 18 | 19 | milvusTotalCountCollector = prometheus.NewGaugeVec(prometheus.GaugeOpts{ 20 | Subsystem: "milvus", 21 | Name: "total_count", 22 | Help: "Total count of milvus in different status", 23 | }, []string{"status"}) 24 | ) 25 | 26 | // MilvusStatusCode for milvusStatusCollector 27 | const ( 28 | MilvusStatusCodePending = float64(0) 29 | MilvusStatusCodeHealthy = float64(1) 30 | MilvusStatusCodeUnHealthy = float64(2) 31 | MilvusStatusCodeDeleting = float64(3) 32 | MilvusStautsCodeStopped = float64(4) 33 | MilvusStautsCodeMaintaining = float64(5) 34 | ) 35 | 36 | func MilvusStatusToCode(status v1beta1.MilvusHealthStatus, isMaintaining bool) float64 { 37 | if isMaintaining { 38 | return MilvusStautsCodeMaintaining 39 | } 40 | switch status { 41 | case v1beta1.StatusHealthy: 42 | return MilvusStatusCodeHealthy 43 | case v1beta1.StatusUnhealthy: 44 | return MilvusStatusCodeUnHealthy 45 | case v1beta1.StatusDeleting: 46 | return MilvusStatusCodeDeleting 47 | case v1beta1.StatusStopped: 48 | return MilvusStautsCodeStopped 49 | default: 50 | return MilvusStatusCodePending 51 | } 52 | } 53 | 54 | // InitializeMetrics for controllers 55 | func InitializeMetrics() { 56 | // register our own 57 | metrics.Registry.MustRegister(milvusStatusCollector) 58 | metrics.Registry.MustRegister(milvusTotalCountCollector) 59 | 60 | // Register a build info metric. 61 | version.Version = v1beta1.Version 62 | metrics.Registry.MustRegister(versioncollector.NewCollector("milvus_operator")) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/controllers/pvc_test.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "go.uber.org/mock/gomock" 9 | corev1 "k8s.io/api/core/v1" 10 | kerrors "k8s.io/apimachinery/pkg/api/errors" 11 | "k8s.io/apimachinery/pkg/runtime/schema" 12 | ) 13 | 14 | func TestMilvusReconciler_ReconcilePVCs(t *testing.T) { 15 | env := newTestEnv(t) 16 | defer env.checkMocks() 17 | r := env.Reconciler 18 | mockClient := env.MockClient 19 | ctx := env.ctx 20 | m := env.Inst 21 | errNotFound := kerrors.NewNotFound(schema.GroupResource{}, "") 22 | 23 | t.Run("persistence_disabled", func(t *testing.T) { 24 | err := r.ReconcilePVCs(ctx, m) 25 | assert.NoError(t, err) 26 | }) 27 | 28 | m.Spec.Dep.RocksMQ.Persistence.Enabled = true 29 | m.Spec.Dep.RocksMQ.Persistence.PersistentVolumeClaim.ExistingClaim = "claim" 30 | t.Run("using_existing", func(t *testing.T) { 31 | err := r.ReconcilePVCs(ctx, m) 32 | assert.NoError(t, err) 33 | }) 34 | 35 | m.Spec.Dep.RocksMQ.Persistence.PersistentVolumeClaim.ExistingClaim = "" 36 | m.Namespace = "ns" 37 | m.Name = "name" 38 | errMock := errors.New("mock") 39 | t.Run("sync:get_old_failed", func(t *testing.T) { 40 | defer env.Ctrl.Finish() 41 | mockClient.EXPECT().Get(ctx, NamespacedName(m.Namespace, getPVCNameByInstName(m.Name)), gomock.Any()).Return(errMock) 42 | err := r.ReconcilePVCs(ctx, m) 43 | assert.Error(t, err) 44 | }) 45 | 46 | t.Run("sync:create_new", func(t *testing.T) { 47 | defer env.Ctrl.Finish() 48 | mockClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(errNotFound) 49 | mockClient.EXPECT().Create(ctx, gomock.Any()).Return(nil) 50 | err := r.ReconcilePVCs(ctx, m) 51 | assert.NoError(t, err) 52 | }) 53 | 54 | t.Run("sync:no_update", func(t *testing.T) { 55 | defer env.Ctrl.Finish() 56 | mockClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Do(func(_, _, obj interface{}, opts ...any) { 57 | pvc := obj.(*corev1.PersistentVolumeClaim) 58 | r.syncPVC(ctx, m.Spec.Dep.RocksMQ.Persistence.PersistentVolumeClaim, pvc) 59 | }).Return(nil) 60 | err := r.ReconcilePVCs(ctx, m) 61 | assert.NoError(t, err) 62 | }) 63 | 64 | m.Spec.Dep.RocksMQ.Persistence.PersistentVolumeClaim.Annotations = map[string]string{"bla": "bla"} 65 | t.Run("sync:update", func(t *testing.T) { 66 | defer env.Ctrl.Finish() 67 | mockClient.EXPECT().Get(ctx, gomock.Any(), gomock.Any()).Return(nil) 68 | mockClient.EXPECT().Update(ctx, gomock.Any()).Return(nil) 69 | err := r.ReconcilePVCs(ctx, m) 70 | assert.NoError(t, err) 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /pkg/controllers/rolling_mode_status_updater.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/pkg/errors" 7 | "sigs.k8s.io/controller-runtime/pkg/client" 8 | 9 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 10 | ) 11 | 12 | //go:generate mockgen -package=controllers -source=rolling_mode_status_updater.go -destination=./rolling_mode_status_updater_mock.go RollingModeStatusUpdater 13 | 14 | type RollingModeStatusUpdater interface { 15 | Update(ctx context.Context, mc *v1beta1.Milvus) error 16 | } 17 | 18 | type RollingModeStatusUpdaterImpl struct { 19 | cli client.Client 20 | bizFactory DeployControllerBizFactory 21 | } 22 | 23 | func NewRollingModeStatusUpdater(cli client.Client, bizFactory DeployControllerBizFactory) RollingModeStatusUpdater { 24 | return &RollingModeStatusUpdaterImpl{ 25 | cli: cli, 26 | bizFactory: bizFactory, 27 | } 28 | } 29 | 30 | func GetExpectedTwoDeployComponents(spec v1beta1.MilvusSpec) []MilvusComponent { 31 | switch spec.Com.RollingMode { 32 | case v1beta1.RollingModeV3: 33 | return GetComponentsBySpec(spec) 34 | default: 35 | if spec.Mode == v1beta1.MilvusModeStandalone { 36 | return []MilvusComponent{} 37 | } 38 | return []MilvusComponent{QueryNode} 39 | } 40 | } 41 | 42 | func (c *RollingModeStatusUpdaterImpl) checkUpdated(ctx context.Context, mc *v1beta1.Milvus) (updated bool, err error) { 43 | if mc.Status.RollingMode == mc.Spec.Com.RollingMode { 44 | return false, nil 45 | } 46 | for _, component := range GetExpectedTwoDeployComponents(mc.Spec) { 47 | biz := c.bizFactory.GetBiz(component) 48 | deployMode, err := biz.CheckDeployMode(ctx, *mc) 49 | if err != nil { 50 | return false, errors.Wrap(err, "check deploy mode") 51 | } 52 | if deployMode != v1beta1.TwoDeployMode { 53 | return false, nil 54 | } 55 | } 56 | mc.Status.RollingMode = mc.Spec.Com.RollingMode 57 | return true, nil 58 | } 59 | 60 | func (c *RollingModeStatusUpdaterImpl) Update(ctx context.Context, mc *v1beta1.Milvus) error { 61 | updated, err := c.checkUpdated(ctx, mc) 62 | if err != nil { 63 | return errors.Wrap(err, "check updated") 64 | } 65 | if !updated { 66 | return nil 67 | } 68 | err = c.cli.Status().Update(ctx, mc) 69 | return errors.Wrap(err, "update milvus status") 70 | } 71 | -------------------------------------------------------------------------------- /pkg/external/iam/aws.go: -------------------------------------------------------------------------------- 1 | package iam 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/minio/minio-go/v7" 7 | "github.com/minio/minio-go/v7/pkg/credentials" 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func VerifyAWS(ctx context.Context, bucketName, region, address string, secure bool) error { 12 | // Initialize minio client object. 13 | client, err := minio.New(address, &minio.Options{ 14 | Creds: credentials.NewIAM(""), 15 | Secure: secure, 16 | Region: region, 17 | }) 18 | if err != nil { 19 | return errors.Wrap(err, "init minio client failed") 20 | } 21 | _, err = client.BucketExists(ctx, bucketName) 22 | return errors.Wrapf(err, "access aws bucket[%s] failed", bucketName) 23 | } 24 | -------------------------------------------------------------------------------- /pkg/external/iam/azure.go: -------------------------------------------------------------------------------- 1 | package iam 2 | 3 | import ( 4 | "context" 5 | "os" 6 | 7 | "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 8 | "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" 9 | "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | type VerifyAzureParams struct { 14 | StorageAccount string 15 | ContainerName string 16 | } 17 | 18 | func VerifyAzure(ctx context.Context, params VerifyAzureParams) error { 19 | cred, err := azidentity.NewWorkloadIdentityCredential(&azidentity.WorkloadIdentityCredentialOptions{ 20 | ClientID: os.Getenv("AZURE_CLIENT_ID"), 21 | TenantID: os.Getenv("AZURE_TENANT_ID"), 22 | TokenFilePath: os.Getenv("AZURE_FEDERATED_TOKEN_FILE"), 23 | }) 24 | if err != nil { 25 | return errors.Wrap(err, "init azure workload identity credential failed") 26 | } 27 | client, err := service.NewClient("https://"+params.StorageAccount+".blob.core.windows.net/", cred, &service.ClientOptions{}) 28 | if err != nil { 29 | return errors.Wrap(err, "init azure storage client failed") 30 | } 31 | _, err = client.NewContainerClient(params.ContainerName).GetProperties(ctx, &container.GetPropertiesOptions{}) 32 | return errors.Wrapf(err, "access azure container[%s] properties failed", params.ContainerName) 33 | } 34 | -------------------------------------------------------------------------------- /pkg/external/iam/gcp.go: -------------------------------------------------------------------------------- 1 | package iam 2 | 3 | import ( 4 | "context" 5 | 6 | "cloud.google.com/go/storage" 7 | "github.com/pkg/errors" 8 | "golang.org/x/oauth2/google" 9 | "google.golang.org/api/option" 10 | ) 11 | 12 | func VerifyGCP(ctx context.Context, bucketName string) error { 13 | tokenSrc := google.ComputeTokenSource("") 14 | client, err := storage.NewClient(ctx, option.WithTokenSource(tokenSrc)) 15 | if err != nil { 16 | return errors.Wrap(err, "init gcp storage client failed") 17 | } 18 | defer client.Close() 19 | _, err = client.Bucket(bucketName).Attrs(ctx) 20 | return errors.Wrapf(err, "access gcp bucket[%s] attrs failed", bucketName) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/external/pulsar.go: -------------------------------------------------------------------------------- 1 | package external 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/apache/pulsar-client-go/pulsar" 7 | "github.com/apache/pulsar-client-go/pulsar/log" 8 | corev1 "k8s.io/api/core/v1" 9 | 10 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 11 | "github.com/zilliztech/milvus-operator/pkg/util" 12 | ) 13 | 14 | type ConditionGetter interface { 15 | GetCondition() v1beta1.MilvusCondition 16 | } 17 | 18 | type PulsarConditionGetter struct { 19 | m *v1beta1.Milvus 20 | } 21 | 22 | var _ ConditionGetter = &PulsarConditionGetter{} 23 | 24 | func NewPulsarConditionGetter(m *v1beta1.Milvus) *PulsarConditionGetter { 25 | 26 | return &PulsarConditionGetter{ 27 | m: m, 28 | } 29 | } 30 | 31 | func newErrMsgStreamCondResult(reason, message string) v1beta1.MilvusCondition { 32 | return v1beta1.MilvusCondition{ 33 | Type: v1beta1.MsgStreamReady, 34 | Status: corev1.ConditionFalse, 35 | Reason: reason, 36 | Message: message, 37 | } 38 | } 39 | 40 | var MQReadyCondition = v1beta1.MilvusCondition{ 41 | Type: v1beta1.MsgStreamReady, 42 | Status: corev1.ConditionTrue, 43 | Reason: v1beta1.ReasonMsgStreamReady, 44 | } 45 | 46 | func (p PulsarConditionGetter) GetCondition() v1beta1.MilvusCondition { 47 | conf := p.m.Spec.Conf 48 | authPlugin, _ := util.GetStringValue(conf.Data, "pulsar", "authPlugin") 49 | endpoint := p.m.Spec.Dep.Pulsar.Endpoint 50 | if authPlugin != "" { 51 | return NewTCPDialConditionGetter(v1beta1.MsgStreamReady, []string{endpoint}).GetCondition() 52 | } 53 | 54 | client, err := pulsarNewClient(pulsar.ClientOptions{ 55 | URL: "pulsar://" + endpoint, 56 | ConnectionTimeout: 2 * time.Second, 57 | OperationTimeout: 3 * time.Second, 58 | Logger: log.DefaultNopLogger(), 59 | }) 60 | 61 | if err != nil { 62 | return newErrMsgStreamCondResult("CreateClientFailed", err.Error()) 63 | } 64 | defer client.Close() 65 | 66 | reader, err := client.CreateReader(pulsar.ReaderOptions{ 67 | Topic: "milvus-operator-topic", 68 | StartMessageID: pulsar.EarliestMessageID(), 69 | }) 70 | if err != nil { 71 | return newErrMsgStreamCondResult("ConnectionFailed", err.Error()) 72 | } 73 | defer reader.Close() 74 | return MQReadyCondition 75 | } 76 | -------------------------------------------------------------------------------- /pkg/external/pulsar_client.go: -------------------------------------------------------------------------------- 1 | package external 2 | 3 | import "github.com/apache/pulsar-client-go/pulsar" 4 | 5 | //go:generate mockgen -package=external -source=pulsar_client.go -destination=pulsar_client_mock.go 6 | 7 | var pulsarNewClient = pulsar.NewClient 8 | 9 | // PulsarClient for mock 10 | type PulsarClient interface { 11 | pulsar.Client 12 | } 13 | 14 | // PulsarReader for mock 15 | type PulsarReader interface { 16 | pulsar.Reader 17 | } 18 | -------------------------------------------------------------------------------- /pkg/external/tcp_dial.go: -------------------------------------------------------------------------------- 1 | package external 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "time" 7 | 8 | corev1 "k8s.io/api/core/v1" 9 | 10 | "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 11 | ) 12 | 13 | type TCPDialConditionGetter struct { 14 | conditionType v1beta1.MilvusConditionType 15 | tcpAddrs []string 16 | } 17 | 18 | var _ ConditionGetter = &TCPDialConditionGetter{} 19 | 20 | func NewTCPDialConditionGetter(conditionType v1beta1.MilvusConditionType, tcpAddrs []string) *TCPDialConditionGetter { 21 | return &TCPDialConditionGetter{ 22 | conditionType: conditionType, 23 | tcpAddrs: tcpAddrs, 24 | } 25 | } 26 | 27 | const dialTimeout = 3 * time.Second 28 | 29 | func (s *TCPDialConditionGetter) GetCondition() v1beta1.MilvusCondition { 30 | for _, addr := range s.tcpAddrs { 31 | conn, err := netDialTimeout("tcp", addr, dialTimeout) 32 | if err != nil { 33 | return v1beta1.MilvusCondition{ 34 | Type: s.conditionType, 35 | Status: corev1.ConditionFalse, 36 | Reason: "ConnectionFailed", 37 | Message: fmt.Sprintf("connect %s failed: %s", addr, err.Error()), 38 | } 39 | } 40 | defer conn.Close() 41 | } 42 | return v1beta1.MilvusCondition{ 43 | Type: s.conditionType, 44 | Status: corev1.ConditionTrue, 45 | Reason: "ConnectionOK", 46 | } 47 | } 48 | 49 | var netDialTimeout = net.DialTimeout 50 | -------------------------------------------------------------------------------- /pkg/helm/interface.go: -------------------------------------------------------------------------------- 1 | package helm 2 | 3 | import ( 4 | "helm.sh/helm/v3/pkg/action" 5 | "helm.sh/helm/v3/pkg/release" 6 | ) 7 | 8 | //go:generate mockgen -source=interface.go -destination=interface_mock.go -package=helm 9 | 10 | // Client interface of helm 11 | type Client interface { 12 | GetStatus(cfg *action.Configuration, releaseName string) (release.Status, error) 13 | GetValues(cfg *action.Configuration, releaseName string) (map[string]interface{}, error) 14 | ReleaseExist(cfg *action.Configuration, releaseName string) (bool, error) 15 | Upgrade(cfg *action.Configuration, request ChartRequest) error 16 | Update(cfg *action.Configuration, request ChartRequest) error 17 | Install(cfg *action.Configuration, request ChartRequest) error 18 | Uninstall(cfg *action.Configuration, releaseName string) error 19 | } 20 | 21 | // SetDefaultClient sets the default client 22 | func SetDefaultClient(client Client) { 23 | defaultClient = client 24 | } 25 | 26 | // defaultClient for focade Client functions 27 | var defaultClient Client = new(LocalClient) 28 | 29 | func GetStatus(cfg *action.Configuration, releaseName string) (release.Status, error) { 30 | return defaultClient.GetStatus(cfg, releaseName) 31 | } 32 | 33 | func GetValues(cfg *action.Configuration, releaseName string) (map[string]interface{}, error) { 34 | return defaultClient.GetValues(cfg, releaseName) 35 | } 36 | 37 | func ReleaseExist(cfg *action.Configuration, releaseName string) (bool, error) { 38 | return defaultClient.ReleaseExist(cfg, releaseName) 39 | } 40 | 41 | func Upgrade(cfg *action.Configuration, request ChartRequest) error { 42 | return defaultClient.Upgrade(cfg, request) 43 | } 44 | 45 | func Update(cfg *action.Configuration, request ChartRequest) error { 46 | return defaultClient.Update(cfg, request) 47 | } 48 | 49 | func Install(cfg *action.Configuration, request ChartRequest) error { 50 | return defaultClient.Install(cfg, request) 51 | } 52 | 53 | func Uninstall(cfg *action.Configuration, releaseName string) error { 54 | return defaultClient.Uninstall(cfg, releaseName) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/helm/values/testing.go: -------------------------------------------------------------------------------- 1 | package values 2 | 3 | // dummyValues is for the convenience of test 4 | type dummyValues struct { 5 | } 6 | 7 | func (dummyValues) GetDefaultValues(dependencyName DependencyKind, chartVersion ChartVersion) map[string]interface{} { 8 | return map[string]interface{}{} 9 | } 10 | -------------------------------------------------------------------------------- /pkg/manager/manager.go: -------------------------------------------------------------------------------- 1 | package manager 2 | 3 | import ( 4 | "time" 5 | 6 | _ "k8s.io/client-go/plugin/pkg/client/auth" 7 | 8 | monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" 9 | "k8s.io/apimachinery/pkg/runtime" 10 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 11 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 12 | ctrl "sigs.k8s.io/controller-runtime" 13 | "sigs.k8s.io/controller-runtime/pkg/cache" 14 | "sigs.k8s.io/controller-runtime/pkg/healthz" 15 | metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" 16 | "sigs.k8s.io/controller-runtime/pkg/webhook" 17 | 18 | milvusiov1alpha1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1alpha1" 19 | milvusiov1beta1 "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 20 | "github.com/zilliztech/milvus-operator/pkg/config" 21 | ) 22 | 23 | var ( 24 | scheme = runtime.NewScheme() 25 | mgrLog = ctrl.Log.WithName("manager") 26 | ) 27 | 28 | func init() { 29 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 30 | 31 | utilruntime.Must(milvusiov1alpha1.AddToScheme(scheme)) 32 | utilruntime.Must(milvusiov1beta1.AddToScheme(scheme)) 33 | utilruntime.Must(monitoringv1.AddToScheme(scheme)) 34 | //+kubebuilder:scaffold:scheme 35 | } 36 | 37 | func NewManager(k8sQps, k8sBurst int, metricsAddr, probeAddr string, enableLeaderElection bool) (ctrl.Manager, error) { 38 | syncPeriod := time.Second * time.Duration(config.SyncIntervalSec) 39 | cacheOptions := cache.Options{ 40 | SyncPeriod: &syncPeriod, 41 | } 42 | metricsOptions := metricsserver.Options{ 43 | BindAddress: metricsAddr, 44 | } 45 | webhookServer := webhook.NewServer(webhook.Options{ 46 | Port: 9443, 47 | }) 48 | ctrlOptions := ctrl.Options{ 49 | Scheme: scheme, 50 | Metrics: metricsOptions, 51 | WebhookServer: webhookServer, 52 | HealthProbeBindAddress: probeAddr, 53 | LeaderElection: enableLeaderElection, 54 | LeaderElectionID: "71808ec5.milvus.io", 55 | Cache: cacheOptions, 56 | } 57 | 58 | conf := ctrl.GetConfigOrDie() 59 | conf.QPS = float32(k8sQps) 60 | conf.Burst = k8sBurst 61 | mgr, err := ctrl.NewManager(conf, ctrlOptions) 62 | if err != nil { 63 | mgrLog.Error(err, "unable to start manager") 64 | return nil, err 65 | } 66 | 67 | //+kubebuilder:scaffold:builder 68 | 69 | if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { 70 | mgrLog.Error(err, "unable to set up health check") 71 | return nil, err 72 | } 73 | if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { 74 | mgrLog.Error(err, "unable to set up ready check") 75 | return nil, err 76 | } 77 | 78 | return mgr, nil 79 | } 80 | -------------------------------------------------------------------------------- /pkg/util/diff.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | reflect "reflect" 5 | 6 | "github.com/davecgh/go-spew/spew" 7 | "github.com/pmezard/go-difflib/difflib" 8 | ) 9 | 10 | func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { 11 | t := reflect.TypeOf(v) 12 | k := t.Kind() 13 | 14 | if k == reflect.Ptr { 15 | t = t.Elem() 16 | k = t.Kind() 17 | } 18 | return t, k 19 | } 20 | 21 | var spewConfig = spew.ConfigState{ 22 | Indent: " ", 23 | DisablePointerAddresses: true, 24 | DisableCapacities: true, 25 | SortKeys: true, 26 | DisableMethods: true, 27 | MaxDepth: 10, 28 | } 29 | 30 | // DiffStr returns a diff of both values as long as both are of the same type and 31 | // are a struct, map, slice, array or string. Otherwise it returns an empty string. 32 | // ref: github.com/stretchr/testify/assert:diff() 33 | func DiffStr(expected interface{}, actual interface{}) string { 34 | if expected == nil || actual == nil { 35 | return "" 36 | } 37 | 38 | et, ek := typeAndKind(expected) 39 | at, _ := typeAndKind(actual) 40 | 41 | if et != at { 42 | return "" 43 | } 44 | 45 | if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { 46 | return "" 47 | } 48 | 49 | var e, a string 50 | if et != reflect.TypeOf("") { 51 | e = spewConfig.Sdump(expected) 52 | a = spewConfig.Sdump(actual) 53 | } else { 54 | e = reflect.ValueOf(expected).String() 55 | a = reflect.ValueOf(actual).String() 56 | } 57 | 58 | diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ 59 | A: difflib.SplitLines(e), 60 | B: difflib.SplitLines(a), 61 | FromFile: "From", 62 | FromDate: "", 63 | ToFile: "To", 64 | ToDate: "", 65 | Context: 1, 66 | }) 67 | 68 | return diff 69 | } 70 | -------------------------------------------------------------------------------- /pkg/util/diff_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestDiffStr(t *testing.T) { 10 | ret := DiffStr("str1", "str2") 11 | assert.NotEmpty(t, ret) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/util/rest/rest_client_test.go: -------------------------------------------------------------------------------- 1 | package rest 2 | 3 | import ( 4 | "context" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ctrl "sigs.k8s.io/controller-runtime" 9 | ) 10 | 11 | func TestNewRestClientImpl(t *testing.T) { 12 | config := ctrl.GetConfigOrDie() 13 | restClient, err := newRestClientImpl(config) 14 | assert.NoError(t, err) 15 | assert.NotNil(t, restClient) 16 | 17 | _, _, err = restClient.Exec(context.TODO(), "test", "test", "test", []string{"/bin/true"}) 18 | // We don't expect this to work in tests. 19 | assert.Error(t, err) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/util/testing.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "runtime" 5 | "strings" 6 | ) 7 | 8 | func GetGitRepoRootDir() string { 9 | _, filename, _, _ := runtime.Caller(0) 10 | return strings.TrimSuffix(filename, "pkg/util/testing.go") 11 | } 12 | -------------------------------------------------------------------------------- /pkg/util/testing_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | 8 | "github.com/zilliztech/milvus-operator/pkg/config" 9 | ) 10 | 11 | func TestGetGitRepoRootDir(t *testing.T) { 12 | repoRoot := GetGitRepoRootDir() 13 | assert.NoError(t, config.Init(repoRoot)) 14 | } 15 | -------------------------------------------------------------------------------- /pkg/util/yamlparser/file.go: -------------------------------------------------------------------------------- 1 | package yamlparser 2 | 3 | import ( 4 | "io" 5 | "os" 6 | "reflect" 7 | 8 | "github.com/pkg/errors" 9 | "gopkg.in/yaml.v3" 10 | ) 11 | 12 | var UserYamlPath = "/milvus/configs/operator/user.yaml" 13 | 14 | type UserYaml struct { 15 | Minio struct { 16 | Address string `yaml:"address"` 17 | Port int `yaml:"port"` 18 | UseSSL bool `yaml:"useSSL"` 19 | UseIAM bool `yaml:"useIAM"` 20 | CloudProvider string `yaml:"cloudProvider"` 21 | AccessKeyID string `yaml:"accessKeyID"` 22 | BucketName string `yaml:"bucketName"` 23 | Region string `yaml:"region"` 24 | } `yaml:"minio"` 25 | } 26 | 27 | func ParseUserYaml() (*UserYaml, error) { 28 | userYaml := new(UserYaml) 29 | err := ParseObjectFromFile(UserYamlPath, userYaml) 30 | return userYaml, err 31 | } 32 | 33 | func ParseObjectFromFile(path string, obj interface{}) error { 34 | file, err := os.Open(path) 35 | if err != nil { 36 | return errors.Wrapf(err, "open file[%s] failed", path) 37 | } 38 | defer file.Close() 39 | fileData, err := io.ReadAll(file) 40 | if err != nil { 41 | return errors.Wrapf(err, "read file[%s] failed", path) 42 | } 43 | err = yaml.Unmarshal(fileData, obj) 44 | return errors.Wrapf(err, "unmarshal file[%s] as type[%s] failed", path, reflect.TypeOf(obj).String()) 45 | } 46 | -------------------------------------------------------------------------------- /pkg/util/yamlparser/file_test.go: -------------------------------------------------------------------------------- 1 | package yamlparser 2 | 3 | import ( 4 | "runtime" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func GetGitRepoRootDir() string { 12 | _, filename, _, _ := runtime.Caller(0) 13 | return strings.TrimSuffix(filename, "pkg/util/yamlparser/file_test.go") 14 | } 15 | 16 | func TestParseUserYaml(t *testing.T) { 17 | t.Run("file not exist", func(t *testing.T) { 18 | UserYamlPath = GetGitRepoRootDir() + "/test/not_exist.yaml" 19 | _, err := ParseUserYaml() 20 | assert.Error(t, err) 21 | }) 22 | t.Run("ok", func(t *testing.T) { 23 | UserYamlPath = GetGitRepoRootDir() + "/test/user.yaml" 24 | ret, err := ParseUserYaml() 25 | assert.NoError(t, err) 26 | assert.Equal(t, "myakid", ret.Minio.AccessKeyID) 27 | assert.Equal(t, "test", ret.Minio.BucketName) 28 | assert.Equal(t, "gcp", ret.Minio.CloudProvider) 29 | assert.Equal(t, "us-east-2", ret.Minio.Region) 30 | assert.True(t, ret.Minio.UseIAM) 31 | }) 32 | 33 | } 34 | -------------------------------------------------------------------------------- /scripts/bump-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | # usage: bump-version.sh 5 | 6 | # semantic version without v, e.g. 1.2.3 7 | OPERATOR_VERSION=$1 8 | MILVUS_VERSION=$2 9 | MILVUS_HELM_VERSION=$3 10 | 11 | SED="sed -i" 12 | if [[ "$(go env GOOS)" == "darwin" ]]; then 13 | SED="sed -i .bak " 14 | fi 15 | 16 | # operator version 17 | ${SED} "s/^VERSION ?= .*/VERSION ?= ${OPERATOR_VERSION}/g" ./Makefile 18 | ${SED} "s/^version: .*/version: ${OPERATOR_VERSION}/g" ./charts/milvus-operator/Chart.yaml 19 | ${SED} "s/^appVersion: .*/appVersion: \"${OPERATOR_VERSION}\"/g" ./charts/milvus-operator/Chart.yaml 20 | ${SED} "s/^ tag: \".*\"/ tag: \"v${OPERATOR_VERSION}\"/g" ./charts/milvus-operator/values.yaml 21 | ${SED} "s|milvus-operator/releases/download/.*/milvus-operator-.*.tgz|milvus-operator/releases/download/v${OPERATOR_VERSION}/milvus-operator-${OPERATOR_VERSION}.tgz|g" ./README.md ./docs/installation/installation.md 22 | ${SED} "s|milvus-operator/.*/deploy/manifests/deployment.yaml|milvus-operator/v${OPERATOR_VERSION}/deploy/manifests/deployment.yaml|g" ./README.md 23 | ${SED} "s|milvus-operator/.*/deploy/manifests/deployment.yaml|milvus-operator/v${OPERATOR_VERSION}/deploy/manifests/deployment.yaml|g" ./docs/installation/installation.md 24 | 25 | # milvus version 26 | ${SED} "s|milvusdb/milvus:.*|milvusdb/milvus:v${MILVUS_VERSION}|g" ./Makefile 27 | ${SED} "s/Versions, v.* \`/Versions, v${MILVUS_VERSION} \`/g" ./README.md 28 | ${SED} "s/Versions| v.* \`/Versions| v${MILVUS_VERSION} \`/g" ./README.md 29 | ${SED} "s/DefaultMilvusVersion = \"v.*\"/DefaultMilvusVersion = \"v${MILVUS_VERSION}\"/g" ./pkg/config/config.go 30 | # milvus-helm version 31 | ${SED} "s/^MILVUS_HELM_VERSION ?= milvus-.*/MILVUS_HELM_VERSION ?= milvus-${MILVUS_HELM_VERSION}/g" ./Makefile 32 | 33 | 34 | make deploy-manifests 35 | -------------------------------------------------------------------------------- /scripts/debug.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | export GOPROXY=https://goproxy.cn 4 | 5 | dlv debug --headless --log --listen :31666 --api-version 2 --accept-multiclient -------------------------------------------------------------------------------- /scripts/init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /cp /run.sh,/merge,/iam-verify /milvus/tools/run.sh,/milvus/tools/merge,/milvus/tools/iam-verify 3 | -------------------------------------------------------------------------------- /scripts/run-helm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | MilvusHelmUserConfigMountPath="/milvus/configs/user.yaml" 4 | MilvusHelmDefaultConfigMountPath="/milvus/configs/default.yaml" 5 | MilvusOriginalConfigPath="/milvus/configs/milvus.yaml" 6 | # merge config 7 | /milvus/tools/merge -s ${MilvusHelmDefaultConfigMountPath} -d ${MilvusOriginalConfigPath} 8 | /milvus/tools/merge -s ${MilvusHelmUserConfigMountPath} -d ${MilvusOriginalConfigPath} 9 | # run commands 10 | exec $@ 11 | -------------------------------------------------------------------------------- /scripts/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | MilvusConfigRootPath="/milvus/configs" 4 | OperatorConfigMountPath="${MilvusConfigRootPath}/operator" 5 | ConfigMapFiles=("user.yaml" "hook.yaml") 6 | LinkFiles=("user.yaml" "hook_updates.yaml") 7 | config_file_count=${#ConfigMapFiles[@]} 8 | # link operator config files to milvus config path 9 | for (( i=0; i<$config_file_count; i++ )); do 10 | if [ -f "${OperatorConfigMountPath}/${ConfigMapFiles[i]}" ]; then 11 | ln -sf "${OperatorConfigMountPath}/${ConfigMapFiles[i]}" "${MilvusConfigRootPath}/${LinkFiles[i]}" 12 | fi 13 | done 14 | 15 | # merge config 16 | MilvusConfigFiles=("milvus.yaml" "hook.yaml") 17 | for (( i=0; i<$config_file_count; i++ )); do 18 | /milvus/tools/merge \ 19 | -s "${OperatorConfigMountPath}/${ConfigMapFiles[i]}" \ 20 | -d "${MilvusConfigRootPath}/${MilvusConfigFiles[i]}" 21 | done 22 | # verify iam 23 | /milvus/tools/iam-verify 24 | # run commands 25 | exec $@ 26 | -------------------------------------------------------------------------------- /test/batch-delete/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/pkg/errors" 7 | "k8s.io/apimachinery/pkg/labels" 8 | ctrl "sigs.k8s.io/controller-runtime" 9 | "sigs.k8s.io/controller-runtime/pkg/client" 10 | 11 | milvusio "github.com/zilliztech/milvus-operator/apis/milvus.io/v1beta1" 12 | ) 13 | 14 | func main() { 15 | err := run() 16 | if err != nil { 17 | panic(err) 18 | } 19 | } 20 | 21 | var minimumMilvus = milvusio.Milvus{ 22 | ObjectMeta: ctrl.ObjectMeta{}, 23 | Spec: milvusio.MilvusSpec{ 24 | Mode: milvusio.MilvusModeStandalone, 25 | Conf: milvusio.Values{ 26 | Data: map[string]interface{}{ 27 | "log": map[string]interface{}{ 28 | "level": "info", 29 | }, 30 | }, 31 | }, 32 | Dep: milvusio.MilvusDependencies{ 33 | Etcd: milvusio.MilvusEtcd{ 34 | InCluster: &milvusio.InClusterConfig{ 35 | DeletionPolicy: milvusio.DeletionPolicyDelete, 36 | PVCDeletion: true, 37 | Values: milvusio.Values{ 38 | Data: map[string]interface{}{ 39 | "replicaCount": 1, 40 | }, 41 | }, 42 | }, 43 | }, 44 | Storage: milvusio.MilvusStorage{ 45 | InCluster: &milvusio.InClusterConfig{ 46 | DeletionPolicy: milvusio.DeletionPolicyDelete, 47 | PVCDeletion: true, 48 | Values: milvusio.Values{ 49 | Data: map[string]interface{}{ 50 | "mode": "standalone", 51 | "resources": map[string]interface{}{ 52 | "requests": map[string]interface{}{ 53 | "memory": "100Mi", 54 | }, 55 | }, 56 | }, 57 | }, 58 | }, 59 | }, 60 | }, 61 | }, 62 | } 63 | 64 | func run() error { 65 | cli, err := getClient() 66 | if err != nil { 67 | return errors.Wrap(err, "getClient error") 68 | } 69 | 70 | ctx := context.Background() 71 | 72 | if err := cli.DeleteAllOf(ctx, &minimumMilvus, &client.DeleteAllOfOptions{ListOptions: client.ListOptions{ 73 | LabelSelector: labels.Set{ 74 | "usage": "batch-test", 75 | }.AsSelector(), 76 | }}); err != nil { 77 | return errors.Wrap(err, "delete milvus error") 78 | } 79 | return nil 80 | } 81 | 82 | func getClient() (client.Client, error) { 83 | conf, err := ctrl.GetConfig() 84 | if err != nil { 85 | return nil, errors.Wrap(err, "failed to get config") 86 | } 87 | scheme, err := milvusio.SchemeBuilder.Build() 88 | if err != nil { 89 | return nil, errors.Wrap(err, "failed to build scheme") 90 | } 91 | cli, err := client.New(conf, client.Options{ 92 | Scheme: scheme, 93 | }) 94 | if err != nil { 95 | return nil, errors.Wrap(err, "failed to create client") 96 | } 97 | return cli, nil 98 | } 99 | -------------------------------------------------------------------------------- /test/hello-milvus-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: hello-milvus 5 | spec: 6 | ttlSecondsAfterFinished: 60 7 | template: 8 | spec: 9 | containers: 10 | - name: hello-milvus 11 | image: bitnami/pymilvus:2.4.6 12 | command: 13 | - "python3" 14 | args: 15 | - "/data/hello-milvus.py" 16 | volumeMounts: 17 | - name: hello-milvus 18 | mountPath: /data 19 | restartPolicy: Never 20 | volumes: 21 | - name: hello-milvus 22 | configMap: 23 | name: hello-milvus 24 | items: 25 | - key: "hello-milvus.py" 26 | path: "hello-milvus.py" 27 | 28 | -------------------------------------------------------------------------------- /test/milvus-2.4.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: milvus.io/v1beta1 2 | kind: Milvus 3 | metadata: 4 | name: my-release 5 | labels: 6 | app: milvus 7 | spec: 8 | components: 9 | image: "milvusdb/milvus:v2.4.17" 10 | disableMetric: true 11 | dependencies: 12 | etcd: 13 | inCluster: 14 | values: 15 | replicaCount: 1 16 | deletionPolicy: Delete 17 | pvcDeletion: true 18 | storage: 19 | inCluster: 20 | values: 21 | mode: standalone 22 | resources: 23 | requests: 24 | memory: 100Mi 25 | persistence: 26 | size: 20Gi 27 | deletionPolicy: Delete 28 | pvcDeletion: true 29 | -------------------------------------------------------------------------------- /test/milvus-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -u -o pipefail 3 | 4 | release="my-release" 5 | 6 | get_cluster_status() { 7 | kubectl get milvus -o yaml "${release}" | yq eval ".status.conditions" 8 | } 9 | 10 | echo "INFO: Deploying old milvus" 11 | if ! kubectl apply -f test/milvus-2.4.yaml ; then 12 | echo "ERROR: Failed to setup test cluster" 13 | exit 1 14 | fi 15 | echo "INFO: Wait for MilvusReady" 16 | if ! kubectl --timeout 10m wait --for=condition=MilvusReady milvus "${release}" ; then 17 | echo "ERROR: Test cluster failed to become ready" 18 | exit 1 19 | fi 20 | get_cluster_status 21 | echo "INFO: Upgrade" 22 | if ! kubectl patch -f test/milvus-2.4.yaml --patch-file=test/patch-2.5.yaml --type=merge ; then 23 | echo "ERROR: Failed to patch test cluster" 24 | exit 1 25 | fi 26 | for i in {1..3} ; do 27 | echo "INFO: Sleeping" 28 | get_cluster_status 29 | sleep 10 30 | done 31 | get_cluster_status 32 | echo "INFO: Wait for MilvusUpdated" 33 | if ! kubectl --timeout 10m wait --for=condition=MilvusUpdated milvus "${release}" ; then 34 | echo "ERROR: Test cluster failed to become updated" 35 | get_cluster_status 36 | exit 1 37 | fi 38 | echo "INFO: Wait for MilvusReady" 39 | if ! kubectl --timeout 5m wait --for=condition=MilvusReady milvus "${release}" ; then 40 | echo "ERROR: Test cluster failed to become updated" 41 | get_cluster_status 42 | exit 1 43 | fi 44 | echo "INFO: Clean up" 45 | if ! kubectl delete -f test/milvus-2.4.yaml --wait=true --timeout=5m --cascade=foreground ; then 46 | echo "ERROR: Test cluster failed to be deleted" 47 | get_cluster_status 48 | exit 1 49 | fi 50 | -------------------------------------------------------------------------------- /test/min-mc-alpha.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mc-sit 6 | --- 7 | apiVersion: milvus.io/v1alpha1 8 | kind: MilvusCluster 9 | metadata: 10 | name: milvus 11 | namespace: mc-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | components: 16 | disableMetric: true 17 | proxy: 18 | serviceLabels: 19 | myLabel: value 20 | serviceAnnotations: 21 | myAnnotation: value 22 | ingress: 23 | labels: 24 | ingressLabel: value 25 | annotations: 26 | ingressAnnotation: value 27 | hosts: ["mc-sit.milvus.io"] 28 | dependencies: 29 | etcd: 30 | inCluster: 31 | deletionPolicy: Delete 32 | pvcDeletion: true 33 | values: 34 | replicaCount: 1 35 | msgStreamType: kafka 36 | kafka: 37 | inCluster: 38 | deletionPolicy: Delete 39 | pvcDeletion: true 40 | values: 41 | persistence: 42 | enabled: true 43 | storageClass: 44 | accessMode: ReadWriteOnce 45 | size: 20Gi 46 | heapOpts: -Xmx512m -Xms320m 47 | defaultReplicationFactor: 1 48 | offsetsTopicReplicationFactor: 1 49 | replicaCount: 1 50 | zookeeper: 51 | replicaCount: 1 52 | storage: 53 | inCluster: 54 | deletionPolicy: Delete 55 | pvcDeletion: true 56 | values: 57 | mode: standalone 58 | persistence: 59 | size: 20Gi 60 | config: 61 | milvus: 62 | log: 63 | level: info 64 | component: 65 | proxy: 66 | timeTickInterval: 150 67 | -------------------------------------------------------------------------------- /test/min-mc-kafka.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mc-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: mc-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | mode: "cluster" 16 | components: 17 | proxy: 18 | serviceLabels: 19 | myLabel: value 20 | serviceAnnotations: 21 | myAnnotation: value 22 | ingress: 23 | labels: 24 | ingressLabel: value 25 | annotations: 26 | ingressAnnotation: value 27 | hosts: ["mc-sit.milvus.io"] 28 | dependencies: 29 | etcd: 30 | inCluster: 31 | deletionPolicy: Delete 32 | pvcDeletion: true 33 | values: 34 | replicaCount: 1 35 | msgStreamType: kafka 36 | kafka: 37 | inCluster: 38 | deletionPolicy: Delete 39 | pvcDeletion: true 40 | values: 41 | persistence: 42 | enabled: true 43 | storageClass: 44 | accessMode: ReadWriteOnce 45 | size: 20Gi 46 | heapOpts: -Xmx512m -Xms320m 47 | defaultReplicationFactor: 1 48 | offsetsTopicReplicationFactor: 1 49 | replicaCount: 1 50 | zookeeper: 51 | replicaCount: 1 52 | storage: 53 | inCluster: 54 | deletionPolicy: Delete 55 | pvcDeletion: true 56 | values: 57 | mode: standalone 58 | persistence: 59 | size: 20Gi 60 | config: 61 | milvus: 62 | log: 63 | level: info 64 | component: 65 | proxy: 66 | timeTickInterval: 150 67 | -------------------------------------------------------------------------------- /test/min-mc-mixture.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mc-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: mc-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | mode: "cluster" 16 | components: 17 | disableMetric: true 18 | mixCoord: 19 | replicas: 1 20 | proxy: 21 | serviceLabels: 22 | myLabel: value 23 | serviceAnnotations: 24 | myAnnotation: value 25 | ingress: 26 | labels: 27 | ingressLabel: value 28 | annotations: 29 | ingressAnnotation: value 30 | hosts: ["mc-sit.milvus.io"] 31 | dependencies: 32 | etcd: 33 | inCluster: 34 | deletionPolicy: Delete 35 | pvcDeletion: true 36 | values: 37 | replicaCount: 1 38 | msgStreamType: kafka 39 | kafka: 40 | inCluster: 41 | deletionPolicy: Delete 42 | pvcDeletion: true 43 | values: 44 | persistence: 45 | enabled: true 46 | storageClass: 47 | accessMode: ReadWriteOnce 48 | size: 20Gi 49 | heapOpts: -Xmx512m -Xms320m 50 | defaultReplicationFactor: 1 51 | offsetsTopicReplicationFactor: 1 52 | replicaCount: 1 53 | zookeeper: 54 | replicaCount: 1 55 | storage: 56 | inCluster: 57 | deletionPolicy: Delete 58 | pvcDeletion: true 59 | values: 60 | mode: standalone 61 | persistence: 62 | size: 20Gi 63 | config: 64 | milvus: 65 | log: 66 | level: info 67 | component: 68 | proxy: 69 | timeTickInterval: 150 70 | -------------------------------------------------------------------------------- /test/min-mc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: mc-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: mc-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | mode: "cluster" 16 | components: 17 | disableMetric: true 18 | proxy: 19 | serviceLabels: 20 | myLabel: value 21 | serviceAnnotations: 22 | myAnnotation: value 23 | ingress: 24 | labels: 25 | ingressLabel: value 26 | annotations: 27 | ingressAnnotation: value 28 | hosts: ["mc-sit.milvus.io"] 29 | dependencies: 30 | etcd: 31 | inCluster: 32 | deletionPolicy: Delete 33 | pvcDeletion: true 34 | values: 35 | replicaCount: 1 36 | msgStreamType: kafka 37 | kafka: 38 | inCluster: 39 | deletionPolicy: Delete 40 | pvcDeletion: true 41 | values: 42 | persistence: 43 | enabled: true 44 | storageClass: 45 | accessMode: ReadWriteOnce 46 | size: 20Gi 47 | heapOpts: -Xmx512m -Xms320m 48 | defaultReplicationFactor: 1 49 | offsetsTopicReplicationFactor: 1 50 | replicaCount: 1 51 | zookeeper: 52 | replicaCount: 1 53 | storage: 54 | inCluster: 55 | deletionPolicy: Delete 56 | pvcDeletion: true 57 | values: 58 | mode: standalone 59 | persistence: 60 | size: 20Gi 61 | config: 62 | milvus: 63 | log: 64 | level: info 65 | component: 66 | proxy: 67 | timeTickInterval: 150 68 | -------------------------------------------------------------------------------- /test/min-milvus-alpha.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: milvus-sit 6 | --- 7 | apiVersion: milvus.io/v1alpha1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: milvus-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | disableMetric: true 16 | ingress: 17 | labels: 18 | ingressLabel: value 19 | annotations: 20 | ingressAnnotation: value 21 | hosts: ["mc-sit.milvus.io"] 22 | serviceLabels: 23 | myLabel: value 24 | serviceAnnotations: 25 | myAnnotation: value 26 | dependencies: 27 | etcd: 28 | inCluster: 29 | deletionPolicy: Delete 30 | pvcDeletion: true 31 | values: 32 | replicaCount: 1 33 | storage: 34 | inCluster: 35 | deletionPolicy: Delete 36 | pvcDeletion: true 37 | values: 38 | mode: standalone 39 | persistence: 40 | size: 20Gi 41 | rocksmq: 42 | persistence: 43 | enabled: true 44 | persistentVolumeClaim: 45 | spec: 46 | resources: 47 | limits: 48 | storage: 20Gi 49 | persistence: 50 | enabled: true 51 | config: 52 | milvus: 53 | log: 54 | level: info 55 | component: 56 | proxy: 57 | timeTickInterval: 150 58 | -------------------------------------------------------------------------------- /test/min-milvus-kafka.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: milvus-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: milvus-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | mode: "standalone" 16 | components: 17 | disableMetric: true 18 | standalone: 19 | ingress: 20 | labels: 21 | ingressLabel: value 22 | annotations: 23 | ingressAnnotation: value 24 | hosts: ["mc-sit.milvus.io"] 25 | serviceLabels: 26 | myLabel: value 27 | serviceAnnotations: 28 | myAnnotation: value 29 | dependencies: 30 | etcd: 31 | inCluster: 32 | deletionPolicy: Delete 33 | pvcDeletion: true 34 | values: 35 | replicaCount: 1 36 | msgStreamType: kafka 37 | kafka: 38 | inCluster: 39 | deletionPolicy: Delete 40 | pvcDeletion: true 41 | values: 42 | defaultReplicationFactor: 1 43 | offsetsTopicReplicationFactor: 1 44 | replicaCount: 1 45 | zookeeper: 46 | replicaCount: 1 47 | storage: 48 | inCluster: 49 | deletionPolicy: Delete 50 | pvcDeletion: true 51 | values: 52 | mode: standalone 53 | persistence: 54 | size: 20Gi 55 | config: 56 | milvus: 57 | log: 58 | level: info 59 | component: 60 | proxy: 61 | timeTickInterval: 150 62 | -------------------------------------------------------------------------------- /test/min-milvus.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Namespace 4 | metadata: 5 | name: milvus-sit 6 | --- 7 | apiVersion: milvus.io/v1beta1 8 | kind: Milvus 9 | metadata: 10 | name: milvus 11 | namespace: milvus-sit 12 | labels: 13 | app: milvus 14 | spec: 15 | mode: "standalone" 16 | components: 17 | disableMetric: true 18 | standalone: 19 | ingress: 20 | labels: 21 | ingressLabel: value 22 | annotations: 23 | ingressAnnotation: value 24 | hosts: ["mc-sit.milvus.io"] 25 | serviceLabels: 26 | myLabel: value 27 | serviceAnnotations: 28 | myAnnotation: value 29 | dependencies: 30 | etcd: 31 | inCluster: 32 | deletionPolicy: Delete 33 | pvcDeletion: true 34 | values: 35 | replicaCount: 1 36 | storage: 37 | inCluster: 38 | deletionPolicy: Delete 39 | pvcDeletion: true 40 | values: 41 | mode: standalone 42 | resources: 43 | requests: 44 | memory: 100Mi 45 | persistence: 46 | size: 20Gi 47 | rocksmq: 48 | persistence: 49 | enabled: true 50 | persistentVolumeClaim: 51 | spec: 52 | resources: 53 | limits: 54 | storage: 20Gi 55 | config: 56 | milvus: 57 | log: 58 | level: info 59 | component: 60 | proxy: 61 | timeTickInterval: 150 62 | -------------------------------------------------------------------------------- /test/patch-2.5.yaml: -------------------------------------------------------------------------------- 1 | spec: 2 | components: 3 | image: "milvusdb/milvus:v2.5.4" 4 | -------------------------------------------------------------------------------- /test/upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | echo "Deploying old operator" 4 | helm -n milvus-operator install --timeout 20m --wait --wait-for-jobs --set resources.requests.cpu=10m --create-namespace milvus-operator https://github.com/zilliztech/milvus-operator/releases/download/v0.9.17/milvus-operator-0.9.17.tgz 5 | kubectl apply -f config/samples/demo.yaml 6 | echo "Deploying milvus" 7 | kubectl --timeout 20m wait --for=condition=MilvusReady milvus my-release 8 | echo "Deploying upgrade" 9 | helm -n milvus-operator upgrade --wait --timeout 10m --reuse-values --set image.repository=milvus-operator,image.tag=sit milvus-operator ./charts/milvus-operator 10 | sleep 60 11 | kubectl get pods 12 | kubectl --timeout 10m wait --for=condition=MilvusReady milvus my-release 13 | # check dependencies no revision change 14 | helm list 15 | helm list |grep -v NAME |awk '{print $3}' | xargs -I{} [ {} -eq "1" ] 16 | # check milvus pods no restart 17 | kubectl get pods 18 | kubectl get pods |grep -v NAME |awk '{print $4}' | xargs -I{} [ {} -eq "0" ] 19 | -------------------------------------------------------------------------------- /test/user.yaml: -------------------------------------------------------------------------------- 1 | dummy: dummy 2 | minio: 3 | accessKeyID: myakid 4 | bucketName: test 5 | useIAM: true 6 | cloudProvider: gcp 7 | region: us-east-2 -------------------------------------------------------------------------------- /test/values.yaml: -------------------------------------------------------------------------------- 1 | pulsar: 2 | replicas: 3 3 | etcd: 4 | replicas: 3 5 | minio: 6 | replicas: 3 7 | kafka: 8 | replcias: 3 -------------------------------------------------------------------------------- /tool.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.24 as builder 2 | 3 | WORKDIR /workspace 4 | # ENV GOPROXY https://goproxy.cn 5 | # Copy the Go Modules manifests 6 | # # cache deps before building and copying source so that we don't need to re-download as much 7 | # # and so that source changes don't invalidate our downloaded layer 8 | # 9 | # # Copy the go source 10 | COPY go.mod go.mod 11 | COPY go.sum go.sum 12 | RUN go mod download 13 | # 14 | # # Build 15 | COPY main.go main.go 16 | COPY apis/ apis/ 17 | COPY pkg/ pkg/ 18 | COPY tool/ tool/ 19 | COPY config/assets/templates out/config/assets/templates 20 | COPY scripts/ scripts/ 21 | COPY Makefile Makefile 22 | RUN make docker-tool-prepare 23 | # 24 | # # Use distroless as minimal base image to package the manager binary 25 | # # Refer to https://github.com/GoogleContainerTools/distroless for more details 26 | FROM gcr.io/distroless/static:nonroot 27 | WORKDIR / 28 | COPY --from=builder /workspace/out/tool / 29 | 30 | USER 65532:65532 31 | -------------------------------------------------------------------------------- /tool/cp/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "flag" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | flag.Parse() 12 | args := flag.Args() 13 | if len(args) != 2 { 14 | println("need 2 parameters") 15 | os.Exit(1) 16 | return 17 | } 18 | srcFiles := strings.Split(args[0], ",") 19 | dstFiles := strings.Split(args[1], ",") 20 | 21 | for i := 0; i < len(srcFiles); i++ { 22 | if err := cp(srcFiles[i], dstFiles[i]); err != nil { 23 | println(err.Error()) 24 | os.Exit(1) 25 | return 26 | } 27 | } 28 | } 29 | 30 | func cp(src, dst string) error { 31 | srcInfo, err := os.Stat(src) 32 | if err != nil { 33 | return errors.New("stat source file failed: " + err.Error()) 34 | } 35 | 36 | data, err := os.ReadFile(src) 37 | if err != nil { 38 | return errors.New("read source file failed: " + err.Error()) 39 | } 40 | 41 | err = os.WriteFile(dst, data, srcInfo.Mode()) 42 | if err != nil { 43 | return errors.New("write destination file failed: " + err.Error()) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /tool/iam-verify/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "os" 8 | "time" 9 | 10 | "github.com/zilliztech/milvus-operator/pkg/external/iam" 11 | "github.com/zilliztech/milvus-operator/pkg/util/yamlparser" 12 | ) 13 | 14 | // iam-verify command is expected to run in the initContainer before the milvus container starts 15 | // It verifies if it can assume the given role in the environment, and if the bucket is accessible. 16 | // if not, it loops sleep and retries until the conditions are met. 17 | 18 | func main() { 19 | userYaml, err := yamlparser.ParseUserYaml() 20 | if err != nil { 21 | log.Fatalf("parse user.yaml failed: %v\n", err) 22 | } 23 | if !userYaml.Minio.UseIAM { 24 | log.Println("useIAM is false") 25 | os.Exit(0) 26 | return 27 | } 28 | var verifyFunc func(ctx context.Context) error 29 | switch userYaml.Minio.CloudProvider { 30 | case "gcp": 31 | verifyFunc = func(ctx context.Context) error { 32 | return iam.VerifyGCP(ctx, userYaml.Minio.BucketName) 33 | } 34 | case "azure": 35 | verifyFunc = func(ctx context.Context) error { 36 | return iam.VerifyAzure(ctx, iam.VerifyAzureParams{ 37 | StorageAccount: userYaml.Minio.AccessKeyID, 38 | ContainerName: userYaml.Minio.BucketName, 39 | }) 40 | } 41 | case "aws": 42 | verifyFunc = func(ctx context.Context) error { 43 | address := fmt.Sprintf("%s:%d", userYaml.Minio.Address, userYaml.Minio.Port) 44 | return iam.VerifyAWS(ctx, userYaml.Minio.BucketName, userYaml.Minio.Region, address, userYaml.Minio.UseSSL) 45 | } 46 | case "aliyun": 47 | verifyFunc = func(ctx context.Context) error { 48 | address := fmt.Sprintf("%s:%d", userYaml.Minio.Address, userYaml.Minio.Port) 49 | return iam.VerifyAliyun(ctx, userYaml.Minio.BucketName, userYaml.Minio.Region, address, userYaml.Minio.UseSSL) 50 | } 51 | case "tencent": 52 | verifyFunc = func(ctx context.Context) error { 53 | address := fmt.Sprintf("%s:%d", userYaml.Minio.Address, userYaml.Minio.Port) 54 | return iam.VerifyTencent(ctx, userYaml.Minio.BucketName, userYaml.Minio.Region, address, userYaml.Minio.UseSSL) 55 | } 56 | default: 57 | log.Printf("iam-verify for csp %s not implement, assume success\n", userYaml.Minio.CloudProvider) 58 | os.Exit(0) 59 | return 60 | } 61 | for { 62 | func() { 63 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 64 | defer cancel() 65 | err := verifyFunc(ctx) 66 | if err == nil { 67 | log.Println("verify iam success") 68 | os.Exit(0) 69 | return 70 | } 71 | log.Printf("verify iam failed: %v, retry in 5 seconds\n", err) 72 | time.Sleep(time.Second * 5) 73 | }() 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tool/merge/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | "os" 7 | 8 | "sigs.k8s.io/yaml" 9 | 10 | "github.com/zilliztech/milvus-operator/pkg/util" 11 | ) 12 | 13 | var mqConfigsToDelete = map[string]bool{ 14 | "kafka": true, 15 | "rocksmq": true, 16 | "natsmq": true, 17 | "pulsar": true, 18 | } 19 | 20 | func checkFileExists(filepath string) bool { 21 | _, err := os.Stat(filepath) 22 | return err == nil 23 | } 24 | 25 | func main() { 26 | srcPath := flag.String("s", "", "source yaml path, will overwrite the dst config") 27 | dstPath := flag.String("d", "", "destination yaml path, will be overwritten by the src config") 28 | flag.Parse() 29 | 30 | if *srcPath == "" || *dstPath == "" { 31 | flag.CommandLine.Usage() 32 | os.Exit(1) 33 | return 34 | } 35 | 36 | if !checkFileExists(*srcPath) { 37 | log.Println("missing source yaml") 38 | os.Exit(0) 39 | } 40 | if !checkFileExists(*dstPath) { 41 | log.Println("missing destination yaml") 42 | os.Exit(0) 43 | } 44 | 45 | src, err := readYaml(*srcPath) 46 | if err != nil { 47 | log.Fatal("read source yaml failed: ", err) 48 | } 49 | 50 | dst, err := readYaml(*dstPath) 51 | if err != nil { 52 | log.Fatal("read destination yaml failed: ", err) 53 | } 54 | if dst == nil { 55 | dst = map[string]interface{}{} 56 | } 57 | util.MergeValues(dst, src) 58 | 59 | // backward compatibility 60 | // delete mqConfigs not provided by dst 61 | if dst[util.MqTypeConfigKey] == nil { 62 | for mqType := range mqConfigsToDelete { 63 | if dst[mqType] != nil { 64 | mqConfigsToDelete[mqType] = false 65 | } 66 | } 67 | } else { 68 | // delete other mqType 69 | mqType := dst[util.MqTypeConfigKey].(string) 70 | mqConfigsToDelete[mqType] = false 71 | } 72 | 73 | for mqType, toDelete := range mqConfigsToDelete { 74 | if toDelete { 75 | delete(dst, mqType) 76 | } 77 | } 78 | 79 | bs, err := yaml.Marshal(dst) 80 | if err != nil { 81 | log.Fatal("marshal failed: ", err) 82 | } 83 | 84 | if err := os.WriteFile(*dstPath, bs, 0644); err != nil { 85 | log.Fatal("write failed: ", err) 86 | } 87 | } 88 | 89 | // readYaml 90 | func readYaml(path string) (map[string]interface{}, error) { 91 | var data map[string]interface{} 92 | bs, err := os.ReadFile(path) 93 | if err != nil { 94 | return nil, err 95 | } 96 | if err := yaml.Unmarshal(bs, &data); err != nil { 97 | return nil, err 98 | } 99 | return data, nil 100 | } 101 | --------------------------------------------------------------------------------