├── .asf.yaml ├── .github ├── ISSUE_TEMPLATE │ └── issue_template-md.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── codeql-analysis.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── charts └── rocketmq-operator │ ├── .helmignore │ ├── Chart.yaml │ ├── crds │ ├── rocketmq.apache.org_brokers.yaml │ ├── rocketmq.apache.org_consoles.yaml │ ├── rocketmq.apache.org_controllers.yaml │ ├── rocketmq.apache.org_nameservices.yaml │ └── rocketmq.apache.org_topictransfers.yaml │ ├── templates │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── rocketmq-operator-rbac.yaml │ └── serviceaccount.yaml │ └── values.yaml ├── deploy ├── crds │ ├── rocketmq.apache.org_brokers.yaml │ ├── rocketmq.apache.org_consoles.yaml │ ├── rocketmq.apache.org_controllers.yaml │ ├── rocketmq.apache.org_nameservices.yaml │ └── rocketmq.apache.org_topictransfers.yaml ├── operator.yaml ├── role.yaml ├── role_binding.yaml ├── service_account.yaml └── storage │ ├── deploy-storage-class.sh │ ├── hostpath │ └── prepare-host-path.sh │ ├── nfs-client-class.yaml │ ├── nfs-client-sa.yaml │ ├── nfs-client.yaml │ └── remove-storage-class.sh ├── docs ├── cn │ ├── README.md │ └── nfs_install_cn.md ├── en │ └── nfs_install_en.md └── img │ └── operator-arch.png ├── example ├── rocketmq_v1alpha1_broker_cr.yaml ├── rocketmq_v1alpha1_cluster_service.yaml ├── rocketmq_v1alpha1_console_cr.yaml ├── rocketmq_v1alpha1_controller_cr.yaml ├── rocketmq_v1alpha1_nameservice_cr.yaml ├── rocketmq_v1alpha1_rocketmq_cluster.yaml └── rocketmq_v1alpha1_topictransfer_cr.yaml ├── go.mod ├── hack └── boilerplate.go.txt ├── images ├── broker │ └── alpine │ │ ├── Dockerfile │ │ ├── brokerGenConfig.sh │ │ ├── brokerStart.sh │ │ ├── build-broker-image.sh │ │ └── runbroker-customize.sh ├── controller │ └── alpine │ │ ├── Dockerfile │ │ ├── build-controller-image.sh │ │ └── runserver-customize.sh ├── namesrv │ └── alpine │ │ ├── Dockerfile │ │ ├── build-namesrv-image.sh │ │ └── runserver-customize.sh └── try-images.sh ├── install-operator.sh ├── main.go ├── pkg ├── apis │ └── rocketmq │ │ ├── group.go │ │ └── v1alpha1 │ │ ├── broker_types.go │ │ ├── console_types.go │ │ ├── controller_types.go │ │ ├── groupversion_info.go │ │ ├── nameservice_types.go │ │ ├── topictransfer_types.go │ │ └── zz_generated.deepcopy.go ├── constants │ └── constants.go ├── controller │ ├── broker │ │ └── broker_controller.go │ ├── console │ │ └── console_controller.go │ ├── controller │ │ └── dledger_controller.go │ ├── nameservice │ │ └── nameservice_controller.go │ └── topictransfer │ │ └── topictransfer_controller.go ├── share │ └── share.go └── tool │ ├── k8s.go │ └── resource_name.go ├── purge-operator.sh └── version └── version.go /.asf.yaml: -------------------------------------------------------------------------------- 1 | notifications: 2 | commits: commits@rocketmq.apache.org 3 | issues: commits@rocketmq.apache.org 4 | pullrequests: commits@rocketmq.apache.org 5 | jobs: commits@rocketmq.apache.org 6 | discussions: dev@rocketmq.apache.org 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue_template-md.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: issue_template.md 3 | about: Describe this issue template's purpose here. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | --- 11 | name: ISSUE_TEMPLATE 12 | about: Describe this issue template's purpose here. 13 | 14 | --- 15 | 16 | The issue tracker is **ONLY** used for the bug report(feature request need to follow [RIP process](https://github.com/apache/rocketmq/wiki/RocketMQ-Improvement-Proposal)). Keep in mind, please check whether there is an existing same report before you raise a new one. 17 | 18 | Alternately (especially if your communication is not a bug report), you can send mail to our [mailing lists](http://rocketmq.apache.org/about/contact/). We welcome any friendly suggestions, bug fixes, collaboration and other improvements. 19 | 20 | Please ensure that your bug report is clear and that it is complete. Otherwise, we may be unable to understand it or to reproduce it, either of which would prevent us from fixing the bug. We strongly recommend the report(bug report or feature request) could include some hints as the following: 21 | 22 | **BUG REPORT** 23 | 24 | 1. Please describe the issue you observed: 25 | 26 | - What did you do (The steps to reproduce)? 27 | 28 | - What did you expect to see? 29 | 30 | - What did you see instead? 31 | 32 | 2. Please tell us about your environment: 33 | 34 | 3. Other information (e.g. detailed explanation, logs, related issues, suggestions how to fix, etc): 35 | 36 | **FEATURE REQUEST** 37 | 38 | 1. Please describe the feature you are requesting. 39 | 40 | 2. Provide any additional detail on your proposed use case for this feature. 41 | 42 | 2. Indicate the importance of this issue to you (blocker, must-have, should-have, nice-to-have). Are you currently using any workarounds to address this issue? 43 | 44 | 4. If there are some sub-tasks using -[] for each subtask and create a corresponding issue to map to the sub task: 45 | 46 | - [sub-task1-issue-number](example_sub_issue1_link_here): sub-task1 description here, 47 | - [sub-task2-issue-number](example_sub_issue2_link_here): sub-task2 description here, 48 | - ... 49 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What is the purpose of the change 2 | 3 | XXXXX 4 | 5 | ## Brief changelog 6 | 7 | XX 8 | 9 | ## Verifying this change 10 | 11 | XXXX 12 | 13 | **Please go through this checklist to help us incorporate your contribution quickly and easily.** 14 | 15 | Notice: `It would be helpful if you could finish the following checklist (the last one is not necessary) before request the community to review your PR`. 16 | 17 | - [ ] Make sure there is a [Github issue](https://github.com/apache/rocketmq-operator/issues) filed for the change (usually before you start working on it). Trivial changes like typos do not require a Github issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue. 18 | - [ ] Format the pull request title like `[ISSUE #123] Fix UnknownException when host config not exist`. Each commit in the pull request should have a meaningful subject line and body. 19 | - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why. 20 | - [ ] Check RBAC rights for Kubernetes roles. 21 | - [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. 22 | - [ ] Run `make docker-build` to build docker image for operator, try your changes from Pod inside your Kubernetes cluster, **not just locally**. Also provide screenshots to show that the RocketMQ cluster is healthy after the changes. 23 | - [ ] Before committing your changes, remember to run `make manifests` to make sure the CRD files are updated. 24 | - [ ] Update documentation if necessary. 25 | - [ ] If this contribution is large, please file an [Apache Individual Contributor License Agreement](http://www.apache.org/licenses/#clas). 26 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "master" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "master" ] 20 | schedule: 21 | - cron: '40 9 * * 4' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'go' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | .idea 9 | 10 | **/data 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | 18 | **/vendor 19 | 20 | # Temporary Build Files 21 | build/_output 22 | build/_test 23 | # Created by https://www.gitignore.io/api/go,vim,emacs,visualstudiocode 24 | ### Emacs ### 25 | # -*- mode: gitignore; -*- 26 | *~ 27 | \#*\# 28 | /.emacs.desktop 29 | /.emacs.desktop.lock 30 | *.elc 31 | auto-save-list 32 | tramp 33 | .\#* 34 | # Org-mode 35 | .org-id-locations 36 | *_archive 37 | # flymake-mode 38 | *_flymake.* 39 | # eshell files 40 | /eshell/history 41 | /eshell/lastdir 42 | # elpa packages 43 | /elpa/ 44 | # reftex files 45 | *.rel 46 | # AUCTeX auto folder 47 | /auto/ 48 | # cask packages 49 | .cask/ 50 | dist/ 51 | # Flycheck 52 | flycheck_*.el 53 | # server auth directory 54 | /server/ 55 | # projectiles files 56 | .projectile 57 | projectile-bookmarks.eld 58 | # directory configuration 59 | .dir-locals.el 60 | # saveplace 61 | places 62 | # url cache 63 | url/cache/ 64 | # cedet 65 | ede-projects.el 66 | # smex 67 | smex-items 68 | # company-statistics 69 | company-statistics-cache.el 70 | # anaconda-mode 71 | anaconda-mode/ 72 | 73 | ### Vim ### 74 | # swap 75 | .sw[a-p] 76 | .*.sw[a-p] 77 | # session 78 | Session.vim 79 | # temporary 80 | .netrwhist 81 | # auto-generated tag files 82 | tags 83 | ### VisualStudioCode ### 84 | .vscode/* 85 | .history 86 | # End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode 87 | 88 | **/*.zip 89 | **/zz_generated.openapi.go 90 | **/*.sum 91 | *.sum 92 | 93 | 94 | bin -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM --platform=$BUILDPLATFORM golang:1.16 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | COPY go.mod go.mod 7 | COPY go.sum go.sum 8 | # cache deps before building and copying source so that we don't need to re-download as much 9 | # and so that source changes don't invalidate our downloaded layer 10 | RUN go mod download 11 | 12 | # Copy the go source 13 | COPY main.go main.go 14 | COPY pkg/ pkg/ 15 | 16 | # Build 17 | ARG TARGETOS TARGETARCH 18 | RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -a -o manager main.go 19 | 20 | # Use distroless as minimal base image to package the manager binary 21 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 22 | #FROM gcr.io/distroless/static:nonroot 23 | FROM --platform=$TARGETPLATFORM openjdk:8-alpine 24 | 25 | # Install rocketmq release into image 26 | RUN apk add --no-cache bash gettext nmap-ncat openssl busybox-extras 27 | ENV ROCKETMQ_HOME /home/rocketmq 28 | ENV ROCKETMQ_VERSION 4.9.4 29 | WORKDIR ${ROCKETMQ_HOME} 30 | RUN set -eux; \ 31 | apk add --virtual .build-deps curl gnupg unzip; \ 32 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip -o rocketmq.zip; \ 33 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip.asc -o rocketmq.zip.asc; \ 34 | curl -L https://www.apache.org/dist/rocketmq/KEYS -o KEYS; \ 35 | gpg --import KEYS; \ 36 | gpg --batch --verify rocketmq.zip.asc rocketmq.zip; \ 37 | unzip rocketmq.zip; \ 38 | mv rocketmq-*/* . ; \ 39 | chmod a+x * ; \ 40 | rmdir rocketmq-* ; \ 41 | rm rocketmq.zip; \ 42 | apk del .build-deps ; \ 43 | rm -rf /var/cache/apk/* ; \ 44 | rm -rf /tmp/* 45 | RUN chown -R 65532:0 ${ROCKETMQ_HOME} 46 | 47 | # Install controller binary 48 | WORKDIR / 49 | COPY --from=builder /workspace/manager . 50 | USER 65532:65532 51 | 52 | ENTRYPOINT ["/manager"] 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # VERSION defines the project version for the bundle. 2 | # Update this value when you upgrade the version of your project. 3 | # To re-generate a bundle for another specific version without changing the standard setup, you can: 4 | # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) 5 | # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) 6 | VERSION ?= 0.0.1 7 | 8 | # CHANNELS define the bundle channels used in the bundle. 9 | # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") 10 | # To re-generate a bundle for other specific channels without changing the standard setup, you can: 11 | # - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) 12 | # - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") 13 | ifneq ($(origin CHANNELS), undefined) 14 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 15 | endif 16 | 17 | # DEFAULT_CHANNEL defines the default channel used in the bundle. 18 | # Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") 19 | # To re-generate a bundle for any other default channel without changing the default setup, you can: 20 | # - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) 21 | # - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") 22 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 23 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 24 | endif 25 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 26 | 27 | # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. 28 | # This variable is used to construct full image tags for bundle and catalog images. 29 | # 30 | # For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both 31 | # apache.org/operatorsdk-bundle:$VERSION and apache.org/operatorsdk-catalog:$VERSION. 32 | IMAGE_TAG_BASE ?= apache.org/operatorsdk 33 | 34 | # BUNDLE_IMG defines the image:tag used for the bundle. 35 | # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) 36 | BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) 37 | 38 | # Image URL to use all building/pushing image targets 39 | IMG ?= controller:latest 40 | # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. 41 | ENVTEST_K8S_VERSION = 1.22 42 | 43 | OPERATOR_CHART_DIR ?= charts/rocketmq-operator 44 | 45 | # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) 46 | ifeq (,$(shell go env GOBIN)) 47 | GOBIN=$(shell go env GOPATH)/bin 48 | else 49 | GOBIN=$(shell go env GOBIN) 50 | endif 51 | 52 | # Setting SHELL to bash allows bash commands to be executed by recipes. 53 | # This is a requirement for 'setup-envtest.sh' in the test target. 54 | # Options are set to exit when a recipe line exits non-zero or a piped command fails. 55 | SHELL = /usr/bin/env bash -o pipefail 56 | .SHELLFLAGS = -ec 57 | 58 | .PHONY: all 59 | all: build 60 | 61 | ##@ General 62 | 63 | # The help target prints out all targets with their descriptions organized 64 | # beneath their categories. The categories are represented by '##@' and the 65 | # target descriptions by '##'. The awk commands is responsible for reading the 66 | # entire set of makefiles included in this invocation, looking for lines of the 67 | # file as xyz: ## something, and then pretty-format the target and help. Then, 68 | # if there's a line with ##@ something, that gets pretty-printed as a category. 69 | # More info on the usage of ANSI control characters for terminal formatting: 70 | # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters 71 | # More info on the awk command: 72 | # http://linuxcommand.org/lc3_adv_awk.php 73 | 74 | .PHONY: help 75 | help: ## Display this help. 76 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 77 | 78 | ##@ Development 79 | 80 | .PHONY: manifests 81 | manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. 82 | $(CONTROLLER_GEN) rbac:roleName=rocketmq-operator crd:generateEmbeddedObjectMeta=true webhook paths="./..." output:dir=deploy output:crd:artifacts:config=deploy/crds 83 | head -n 14 deploy/role_binding.yaml > deploy/role.yaml.bak 84 | cat deploy/role.yaml >> deploy/role.yaml.bak 85 | rm deploy/role.yaml && mv deploy/role.yaml.bak deploy/role.yaml 86 | mkdir -p $(OPERATOR_CHART_DIR)/crds/ && cp deploy/crds/* $(OPERATOR_CHART_DIR)/crds/ 87 | 88 | .PHONY: generate 89 | generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 90 | $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." 91 | 92 | .PHONY: fmt 93 | fmt: ## Run go fmt against code. 94 | go fmt ./... 95 | 96 | .PHONY: vet 97 | vet: ## Run go vet against code. 98 | go vet ./... 99 | 100 | .PHONY: test 101 | test: manifests generate fmt vet envtest ## Run tests. 102 | KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out 103 | 104 | ##@ Build 105 | 106 | .PHONY: build 107 | build: generate fmt vet ## Build manager binary. 108 | go build -o bin/manager main.go 109 | 110 | .PHONY: run 111 | run: manifests generate fmt vet ## Run a controller from your host. 112 | go run ./main.go 113 | 114 | .PHONY: docker-buildx 115 | docker-buildx: ## Create a new docker builder to support --platform 116 | docker buildx create --name multiarch --driver docker-container --use 117 | 118 | .PHONY: docker-build 119 | docker-build: test docker-buildx ## Build docker image with the manager. 120 | docker buildx build --platform linux/amd64 --load -t ${IMG} . 121 | 122 | .PHONY: docker-push 123 | docker-push: ## Push docker image with the manager. 124 | docker push ${IMG} 125 | 126 | .PHONY: docker-image-release 127 | docker-build: test docker-buildx ## Build docker image with the manager. 128 | docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMG} . 129 | 130 | ##@ Deployment 131 | 132 | ifndef ignore-not-found 133 | ignore-not-found = false 134 | endif 135 | 136 | .PHONY: install 137 | install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. 138 | kubectl apply -f deploy/crds/rocketmq.apache.org_controllers.yaml 139 | kubectl create -f deploy/crds/rocketmq.apache.org_brokers.yaml 140 | kubectl create -f deploy/crds/rocketmq.apache.org_nameservices.yaml 141 | kubectl create -f deploy/crds/rocketmq.apache.org_consoles.yaml 142 | kubectl create -f deploy/crds/rocketmq.apache.org_topictransfers.yaml 143 | 144 | .PHONY: uninstall 145 | uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 146 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/crds/rocketmq.apache.org_brokers.yaml 147 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/crds/rocketmq.apache.org_controllers.yaml 148 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/crds/rocketmq.apache.org_nameservices.yaml 149 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/crds/rocketmq.apache.org_consoles.yaml 150 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/crds/rocketmq.apache.org_topictransfers.yaml 151 | 152 | .PHONY: deploy 153 | deploy: manifests install ## Deploy controller to the K8s cluster specified in ~/.kube/config. 154 | kubectl create -f deploy/service_account.yaml 155 | kubectl create -f deploy/role.yaml 156 | kubectl create -f deploy/role_binding.yaml 157 | kubectl create -f deploy/operator.yaml 158 | 159 | .PHONY: undeploy 160 | undeploy: uninstall ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 161 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/service_account.yaml 162 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/role.yaml 163 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/role_binding.yaml 164 | kubectl delete --ignore-not-found=$(ignore-not-found) -f deploy/operator.yaml 165 | 166 | CONTROLLER_GEN = $(shell pwd)/bin/controller-gen 167 | .PHONY: controller-gen 168 | controller-gen: ## Download controller-gen locally if necessary. 169 | $(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0) 170 | 171 | KUSTOMIZE = $(shell pwd)/bin/kustomize 172 | .PHONY: kustomize 173 | kustomize: ## Download kustomize locally if necessary. 174 | $(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7) 175 | 176 | ENVTEST = $(shell pwd)/bin/setup-envtest 177 | .PHONY: envtest 178 | envtest: ## Download envtest-setup locally if necessary. 179 | $(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest) 180 | 181 | # go-get-tool will 'go get' any package $2 and install it to $1. 182 | PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST)))) 183 | define go-get-tool 184 | @[ -f $(1) ] || { \ 185 | set -e ;\ 186 | TMP_DIR=$$(mktemp -d) ;\ 187 | cd $$TMP_DIR ;\ 188 | go mod init tmp ;\ 189 | echo "Downloading $(2)" ;\ 190 | GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\ 191 | rm -rf $$TMP_DIR ;\ 192 | } 193 | endef 194 | 195 | #.PHONY: bundle 196 | #bundle: manifests kustomize ## Generate bundle manifests and metadata, then validate generated files. 197 | # operator-sdk generate kustomize manifests -q 198 | # cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 199 | # $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 200 | # operator-sdk bundle validate ./bundle 201 | # 202 | #.PHONY: bundle-build 203 | #bundle-build: ## Build the bundle image. 204 | # docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 205 | # 206 | #.PHONY: bundle-push 207 | #bundle-push: ## Push the bundle image. 208 | # $(MAKE) docker-push IMG=$(BUNDLE_IMG) 209 | 210 | .PHONY: opm 211 | OPM = ./bin/opm 212 | opm: ## Download opm locally if necessary. 213 | ifeq (,$(wildcard $(OPM))) 214 | ifeq (,$(shell which opm 2>/dev/null)) 215 | @{ \ 216 | set -e ;\ 217 | mkdir -p $(dir $(OPM)) ;\ 218 | OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ 219 | curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.19.1/$${OS}-$${ARCH}-opm ;\ 220 | chmod +x $(OPM) ;\ 221 | } 222 | else 223 | OPM = $(shell which opm) 224 | endif 225 | endif 226 | 227 | # A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). 228 | # These images MUST exist in a registry and be pull-able. 229 | BUNDLE_IMGS ?= $(BUNDLE_IMG) 230 | 231 | # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). 232 | CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) 233 | 234 | # Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. 235 | ifneq ($(origin CATALOG_BASE_IMG), undefined) 236 | FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) 237 | endif 238 | 239 | # Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. 240 | # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: 241 | # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator 242 | .PHONY: catalog-build 243 | catalog-build: opm ## Build a catalog image. 244 | $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) 245 | 246 | # Push the catalog image. 247 | .PHONY: catalog-push 248 | catalog-push: ## Push a catalog image. 249 | $(MAKE) docker-push IMG=$(CATALOG_IMG) 250 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Apache RocketMQ 2 | Copyright 2016-2021 The Apache Software Foundation 3 | 4 | This product includes software developed at 5 | The Apache Software Foundation (http://www.apache.org/). 6 | -------------------------------------------------------------------------------- /charts/rocketmq-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/rocketmq-operator/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: rocketmq-operator 3 | description: A Helm chart for Kubernetes 4 | # A chart can be either an 'application' or a 'library' chart. 5 | # 6 | # Application charts are a collection of templates that can be packaged into versioned archives 7 | # to be deployed. 8 | # 9 | # Library charts provide useful utilities or functions for the chart developer. They're included as 10 | # a dependency of application charts to inject those utilities and functions into the rendering 11 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 12 | type: application 13 | # This is the chart version. This version number should be incremented each time you make changes 14 | # to the chart and its templates, including the app version. 15 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 16 | version: 0.1.0 17 | # This is the version number of the application being deployed. This version number should be 18 | # incremented each time you make changes to the application. Versions are not expected to 19 | # follow Semantic Versioning. They should reflect the version the application is using. 20 | # It is recommended to use it with quotes. 21 | appVersion: "0.3.0" 22 | -------------------------------------------------------------------------------- /charts/rocketmq-operator/crds/rocketmq.apache.org_topictransfers.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.7.0 8 | creationTimestamp: null 9 | name: topictransfers.rocketmq.apache.org 10 | spec: 11 | group: rocketmq.apache.org 12 | names: 13 | kind: TopicTransfer 14 | listKind: TopicTransferList 15 | plural: topictransfers 16 | singular: topictransfer 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: TopicTransfer is the Schema for the topictransfers API 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: TopicTransferSpec defines the desired state of TopicTransfer 38 | properties: 39 | sourceCluster: 40 | description: The cluster where the transferred topic from 41 | type: string 42 | targetCluster: 43 | description: The cluster where the topic will be transferred to 44 | type: string 45 | topic: 46 | description: Topic name 47 | type: string 48 | type: object 49 | status: 50 | description: TopicTransferStatus defines the observed state of TopicTransfer 51 | type: object 52 | type: object 53 | served: true 54 | storage: true 55 | subresources: 56 | status: {} 57 | status: 58 | acceptedNames: 59 | kind: "" 60 | plural: "" 61 | conditions: [] 62 | storedVersions: [] 63 | -------------------------------------------------------------------------------- /charts/rocketmq-operator/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "rocketmq-operator.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "rocketmq-operator.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "rocketmq-operator.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "rocketmq-operator.labels" -}} 37 | helm.sh/chart: {{ include "rocketmq-operator.chart" . }} 38 | {{ include "rocketmq-operator.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "rocketmq-operator.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "rocketmq-operator.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "rocketmq-operator.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "rocketmq-operator.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /charts/rocketmq-operator/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "rocketmq-operator.fullname" . }} 5 | labels: 6 | {{- include "rocketmq-operator.labels" . | nindent 4 }} 7 | spec: 8 | replicas: {{ .Values.rocketmqOperator.replicas }} 9 | selector: 10 | matchLabels: 11 | name: rocketmq-operator 12 | {{- include "rocketmq-operator.selectorLabels" . | nindent 6 }} 13 | template: 14 | metadata: 15 | labels: 16 | name: rocketmq-operator 17 | {{- include "rocketmq-operator.selectorLabels" . | nindent 8 }} 18 | spec: 19 | containers: 20 | - args: {{- toYaml .Values.rocketmqOperator.manager.args | nindent 8 }} 21 | command: 22 | - /manager 23 | env: 24 | - name: WATCH_NAMESPACE 25 | valueFrom: 26 | fieldRef: 27 | fieldPath: metadata.namespace 28 | - name: POD_NAME 29 | valueFrom: 30 | fieldRef: 31 | fieldPath: metadata.name 32 | - name: OPERATOR_NAME 33 | value: {{ quote .Values.rocketmqOperator.manager.env.operatorName }} 34 | - name: KUBERNETES_CLUSTER_DOMAIN 35 | value: {{ quote .Values.kubernetesClusterDomain }} 36 | image: {{ .Values.rocketmqOperator.manager.image.repository }}:{{ .Values.rocketmqOperator.manager.image.tag 37 | | default .Chart.AppVersion }} 38 | imagePullPolicy: {{ .Values.rocketmqOperator.manager.imagePullPolicy }} 39 | livenessProbe: 40 | httpGet: 41 | path: /healthz 42 | port: 8081 43 | initialDelaySeconds: 15 44 | periodSeconds: 20 45 | name: manager 46 | readinessProbe: 47 | httpGet: 48 | path: /readyz 49 | port: 8081 50 | initialDelaySeconds: 5 51 | periodSeconds: 10 52 | resources: {} 53 | securityContext: {{- toYaml .Values.rocketmqOperator.manager.containerSecurityContext 54 | | nindent 10 }} 55 | serviceAccountName: {{ include "rocketmq-operator.fullname" . }} 56 | terminationGracePeriodSeconds: 10 -------------------------------------------------------------------------------- /charts/rocketmq-operator/templates/rocketmq-operator-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "rocketmq-operator.fullname" . }} 5 | labels: 6 | {{- include "rocketmq-operator.labels" . | nindent 4 }} 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - configmaps 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - events 24 | verbs: 25 | - create 26 | - patch 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - pods 31 | verbs: 32 | - create 33 | - delete 34 | - get 35 | - list 36 | - patch 37 | - update 38 | - watch 39 | - apiGroups: 40 | - "" 41 | resources: 42 | - pods/exec 43 | verbs: 44 | - create 45 | - delete 46 | - get 47 | - list 48 | - patch 49 | - update 50 | - watch 51 | - apiGroups: 52 | - "" 53 | resources: 54 | - services 55 | verbs: 56 | - create 57 | - delete 58 | - get 59 | - list 60 | - patch 61 | - update 62 | - watch 63 | - apiGroups: 64 | - apps 65 | resources: 66 | - deployments 67 | verbs: 68 | - create 69 | - delete 70 | - get 71 | - list 72 | - patch 73 | - update 74 | - watch 75 | - apiGroups: 76 | - apps 77 | resources: 78 | - statefulsets 79 | verbs: 80 | - create 81 | - delete 82 | - get 83 | - list 84 | - patch 85 | - update 86 | - watch 87 | - apiGroups: 88 | - coordination.k8s.io 89 | resources: 90 | - leases 91 | verbs: 92 | - create 93 | - delete 94 | - get 95 | - list 96 | - patch 97 | - update 98 | - watch 99 | - apiGroups: 100 | - rocketmq.apache.org 101 | resources: 102 | - brokers 103 | verbs: 104 | - create 105 | - delete 106 | - get 107 | - list 108 | - patch 109 | - update 110 | - watch 111 | - apiGroups: 112 | - rocketmq.apache.org 113 | resources: 114 | - brokers/finalizers 115 | verbs: 116 | - update 117 | - apiGroups: 118 | - rocketmq.apache.org 119 | resources: 120 | - brokers/status 121 | verbs: 122 | - get 123 | - patch 124 | - update 125 | - apiGroups: 126 | - rocketmq.apache.org 127 | resources: 128 | - consoles 129 | verbs: 130 | - create 131 | - delete 132 | - get 133 | - list 134 | - patch 135 | - update 136 | - watch 137 | - apiGroups: 138 | - rocketmq.apache.org 139 | resources: 140 | - consoles/finalizers 141 | verbs: 142 | - update 143 | - apiGroups: 144 | - rocketmq.apache.org 145 | resources: 146 | - consoles/status 147 | verbs: 148 | - get 149 | - patch 150 | - update 151 | - apiGroups: 152 | - rocketmq.apache.org 153 | resources: 154 | - controllers 155 | verbs: 156 | - create 157 | - delete 158 | - get 159 | - list 160 | - patch 161 | - update 162 | - watch 163 | - apiGroups: 164 | - rocketmq.apache.org 165 | resources: 166 | - controllers/finalizers 167 | verbs: 168 | - update 169 | - apiGroups: 170 | - rocketmq.apache.org 171 | resources: 172 | - controllers/status 173 | verbs: 174 | - get 175 | - patch 176 | - update 177 | - apiGroups: 178 | - rocketmq.apache.org 179 | resources: 180 | - nameservices 181 | verbs: 182 | - create 183 | - delete 184 | - get 185 | - list 186 | - patch 187 | - update 188 | - watch 189 | - apiGroups: 190 | - rocketmq.apache.org 191 | resources: 192 | - nameservices/finalizers 193 | verbs: 194 | - update 195 | - apiGroups: 196 | - rocketmq.apache.org 197 | resources: 198 | - nameservices/status 199 | verbs: 200 | - get 201 | - patch 202 | - update 203 | - apiGroups: 204 | - rocketmq.apache.org 205 | resources: 206 | - topictransfers 207 | verbs: 208 | - create 209 | - delete 210 | - get 211 | - list 212 | - patch 213 | - update 214 | - watch 215 | - apiGroups: 216 | - rocketmq.apache.org 217 | resources: 218 | - topictransfers/finalizers 219 | verbs: 220 | - update 221 | - apiGroups: 222 | - rocketmq.apache.org 223 | resources: 224 | - topictransfers/status 225 | verbs: 226 | - get 227 | - patch 228 | - update 229 | --- 230 | apiVersion: rbac.authorization.k8s.io/v1 231 | kind: ClusterRoleBinding 232 | metadata: 233 | name: {{ include "rocketmq-operator.fullname" . }} 234 | labels: 235 | {{- include "rocketmq-operator.labels" . | nindent 4 }} 236 | roleRef: 237 | apiGroup: rbac.authorization.k8s.io 238 | kind: ClusterRole 239 | name: '{{ include "rocketmq-operator.fullname" . }}' 240 | subjects: 241 | - kind: ServiceAccount 242 | name: '{{ include "rocketmq-operator.fullname" . }}' 243 | namespace: '{{ .Release.Namespace }}' -------------------------------------------------------------------------------- /charts/rocketmq-operator/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ include "rocketmq-operator.fullname" . }} 5 | labels: 6 | {{- include "rocketmq-operator.labels" . | nindent 4 }} 7 | annotations: 8 | {{- toYaml .Values.rocketmqOperator.serviceAccount.annotations | nindent 4 }} -------------------------------------------------------------------------------- /charts/rocketmq-operator/values.yaml: -------------------------------------------------------------------------------- 1 | kubernetesClusterDomain: cluster.local 2 | rocketmqOperator: 3 | manager: 4 | args: 5 | - --leader-elect 6 | containerSecurityContext: 7 | allowPrivilegeEscalation: false 8 | env: 9 | operatorName: rocketmq-operator 10 | image: 11 | repository: apache/rocketmq-operator 12 | tag: latest 13 | imagePullPolicy: IfNotPresent 14 | replicas: 1 15 | serviceAccount: 16 | annotations: {} 17 | -------------------------------------------------------------------------------- /deploy/crds/rocketmq.apache.org_topictransfers.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.7.0 8 | creationTimestamp: null 9 | name: topictransfers.rocketmq.apache.org 10 | spec: 11 | group: rocketmq.apache.org 12 | names: 13 | kind: TopicTransfer 14 | listKind: TopicTransferList 15 | plural: topictransfers 16 | singular: topictransfer 17 | scope: Namespaced 18 | versions: 19 | - name: v1alpha1 20 | schema: 21 | openAPIV3Schema: 22 | description: TopicTransfer is the Schema for the topictransfers API 23 | properties: 24 | apiVersion: 25 | description: 'APIVersion defines the versioned schema of this representation 26 | of an object. Servers should convert recognized schemas to the latest 27 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 28 | type: string 29 | kind: 30 | description: 'Kind is a string value representing the REST resource this 31 | object represents. Servers may infer this from the endpoint the client 32 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 33 | type: string 34 | metadata: 35 | type: object 36 | spec: 37 | description: TopicTransferSpec defines the desired state of TopicTransfer 38 | properties: 39 | sourceCluster: 40 | description: The cluster where the transferred topic from 41 | type: string 42 | targetCluster: 43 | description: The cluster where the topic will be transferred to 44 | type: string 45 | topic: 46 | description: Topic name 47 | type: string 48 | type: object 49 | status: 50 | description: TopicTransferStatus defines the observed state of TopicTransfer 51 | type: object 52 | type: object 53 | served: true 54 | storage: true 55 | subresources: 56 | status: {} 57 | status: 58 | acceptedNames: 59 | kind: "" 60 | plural: "" 61 | conditions: [] 62 | storedVersions: [] 63 | -------------------------------------------------------------------------------- /deploy/operator.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: apps/v1 17 | kind: Deployment 18 | metadata: 19 | name: rocketmq-operator 20 | spec: 21 | replicas: 1 22 | selector: 23 | matchLabels: 24 | name: rocketmq-operator 25 | template: 26 | metadata: 27 | labels: 28 | name: rocketmq-operator 29 | spec: 30 | serviceAccountName: rocketmq-operator 31 | terminationGracePeriodSeconds: 10 32 | containers: 33 | - name: manager 34 | # Replace this with the built image name 35 | image: apache/rocketmq-operator:latest 36 | command: 37 | - /manager 38 | args: 39 | - --leader-elect 40 | imagePullPolicy: IfNotPresent 41 | securityContext: 42 | allowPrivilegeEscalation: false 43 | livenessProbe: 44 | httpGet: 45 | path: /healthz 46 | port: 8081 47 | initialDelaySeconds: 15 48 | periodSeconds: 20 49 | readinessProbe: 50 | httpGet: 51 | path: /readyz 52 | port: 8081 53 | initialDelaySeconds: 5 54 | periodSeconds: 10 55 | env: 56 | - name: WATCH_NAMESPACE 57 | valueFrom: 58 | fieldRef: 59 | fieldPath: metadata.namespace 60 | - name: POD_NAME 61 | valueFrom: 62 | fieldRef: 63 | fieldPath: metadata.name 64 | - name: OPERATOR_NAME 65 | value: "rocketmq-operator" 66 | -------------------------------------------------------------------------------- /deploy/role.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: rbac.authorization.k8s.io/v1 18 | kind: ClusterRole 19 | metadata: 20 | creationTimestamp: null 21 | name: rocketmq-operator 22 | rules: 23 | - apiGroups: 24 | - "" 25 | resources: 26 | - configmaps 27 | verbs: 28 | - create 29 | - delete 30 | - get 31 | - list 32 | - patch 33 | - update 34 | - watch 35 | - apiGroups: 36 | - "" 37 | resources: 38 | - events 39 | verbs: 40 | - create 41 | - patch 42 | - apiGroups: 43 | - "" 44 | resources: 45 | - pods 46 | verbs: 47 | - create 48 | - delete 49 | - get 50 | - list 51 | - patch 52 | - update 53 | - watch 54 | - apiGroups: 55 | - "" 56 | resources: 57 | - pods/exec 58 | verbs: 59 | - create 60 | - delete 61 | - get 62 | - list 63 | - patch 64 | - update 65 | - watch 66 | - apiGroups: 67 | - "" 68 | resources: 69 | - services 70 | verbs: 71 | - create 72 | - delete 73 | - get 74 | - list 75 | - patch 76 | - update 77 | - watch 78 | - apiGroups: 79 | - apps 80 | resources: 81 | - deployments 82 | verbs: 83 | - create 84 | - delete 85 | - get 86 | - list 87 | - patch 88 | - update 89 | - watch 90 | - apiGroups: 91 | - apps 92 | resources: 93 | - statefulsets 94 | verbs: 95 | - create 96 | - delete 97 | - get 98 | - list 99 | - patch 100 | - update 101 | - watch 102 | - apiGroups: 103 | - coordination.k8s.io 104 | resources: 105 | - leases 106 | verbs: 107 | - create 108 | - delete 109 | - get 110 | - list 111 | - patch 112 | - update 113 | - watch 114 | - apiGroups: 115 | - rocketmq.apache.org 116 | resources: 117 | - brokers 118 | verbs: 119 | - create 120 | - delete 121 | - get 122 | - list 123 | - patch 124 | - update 125 | - watch 126 | - apiGroups: 127 | - rocketmq.apache.org 128 | resources: 129 | - brokers/finalizers 130 | verbs: 131 | - update 132 | - apiGroups: 133 | - rocketmq.apache.org 134 | resources: 135 | - brokers/status 136 | verbs: 137 | - get 138 | - patch 139 | - update 140 | - apiGroups: 141 | - rocketmq.apache.org 142 | resources: 143 | - consoles 144 | verbs: 145 | - create 146 | - delete 147 | - get 148 | - list 149 | - patch 150 | - update 151 | - watch 152 | - apiGroups: 153 | - rocketmq.apache.org 154 | resources: 155 | - consoles/finalizers 156 | verbs: 157 | - update 158 | - apiGroups: 159 | - rocketmq.apache.org 160 | resources: 161 | - consoles/status 162 | verbs: 163 | - get 164 | - patch 165 | - update 166 | - apiGroups: 167 | - rocketmq.apache.org 168 | resources: 169 | - controllers 170 | verbs: 171 | - create 172 | - delete 173 | - get 174 | - list 175 | - patch 176 | - update 177 | - watch 178 | - apiGroups: 179 | - rocketmq.apache.org 180 | resources: 181 | - controllers/finalizers 182 | verbs: 183 | - update 184 | - apiGroups: 185 | - rocketmq.apache.org 186 | resources: 187 | - controllers/status 188 | verbs: 189 | - get 190 | - patch 191 | - update 192 | - apiGroups: 193 | - rocketmq.apache.org 194 | resources: 195 | - nameservices 196 | verbs: 197 | - create 198 | - delete 199 | - get 200 | - list 201 | - patch 202 | - update 203 | - watch 204 | - apiGroups: 205 | - rocketmq.apache.org 206 | resources: 207 | - nameservices/finalizers 208 | verbs: 209 | - update 210 | - apiGroups: 211 | - rocketmq.apache.org 212 | resources: 213 | - nameservices/status 214 | verbs: 215 | - get 216 | - patch 217 | - update 218 | - apiGroups: 219 | - rocketmq.apache.org 220 | resources: 221 | - topictransfers 222 | verbs: 223 | - create 224 | - delete 225 | - get 226 | - list 227 | - patch 228 | - update 229 | - watch 230 | - apiGroups: 231 | - rocketmq.apache.org 232 | resources: 233 | - topictransfers/finalizers 234 | verbs: 235 | - update 236 | - apiGroups: 237 | - rocketmq.apache.org 238 | resources: 239 | - topictransfers/status 240 | verbs: 241 | - get 242 | - patch 243 | - update 244 | -------------------------------------------------------------------------------- /deploy/role_binding.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | kind: ClusterRoleBinding 17 | apiVersion: rbac.authorization.k8s.io/v1 18 | metadata: 19 | name: rocketmq-operator 20 | subjects: 21 | - kind: ServiceAccount 22 | name: rocketmq-operator 23 | namespace: default 24 | roleRef: 25 | kind: ClusterRole 26 | name: rocketmq-operator 27 | apiGroup: rbac.authorization.k8s.io 28 | -------------------------------------------------------------------------------- /deploy/service_account.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: v1 17 | kind: ServiceAccount 18 | metadata: 19 | name: rocketmq-operator 20 | -------------------------------------------------------------------------------- /deploy/storage/deploy-storage-class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | kubectl apply -f nfs-client-sa.yaml 19 | kubectl apply -f nfs-client-class.yaml 20 | kubectl apply -f nfs-client.yaml 21 | -------------------------------------------------------------------------------- /deploy/storage/hostpath/prepare-host-path.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | ### Instruction 19 | ### This script helps you create the hostPath dir on your localhost. You may need sudo privilege to run this script! 20 | ### You may need to run this script on every node of your Kubernetes cluster to prepare hostPath. 21 | 22 | ### You can modify the following parameters according to your real deployment requirements ### 23 | # NAME_SERVER_DATA_PATH should be the same with the hostPath field in rocketmq_v1alpha1_nameservice_cr.yaml 24 | NAME_SERVER_DATA_PATH=/data/rocketmq/nameserver 25 | # BROKER_DATA_PATH should be the same with the hostPath field in rocketmq_v1alpha1_broker_cr.yaml 26 | BROKER_DATA_PATH=/data/rocketmq/broker 27 | # CONTROLLER_DATA_PATH should be the same with the hostPath field in rocketmq_v1alpha1_controller_cr.yaml 28 | CONTROLLER_DATA_PATH=/data/rocketmq/controller 29 | # ROCKETMQ_UID and ROCKETMQ_GID should be the same with docker image settings 30 | ROCKETMQ_UID=3000 31 | ROCKETMQ_GID=3000 32 | 33 | 34 | ### prepare hostPath dir for RocketMQ-Operator 35 | prepare_dir() 36 | { 37 | mkdir -p $1 38 | chown -R $2 $1 39 | chgrp -R $3 $1 40 | chmod -R a+rw $1 41 | } 42 | 43 | prepare_dir $BROKER_DATA_PATH $ROCKETMQ_UID $ROCKETMQ_GID 44 | prepare_dir $NAME_SERVER_DATA_PATH $ROCKETMQ_UID $ROCKETMQ_GID 45 | prepare_dir $CONTROLLER_DATA_PATH $ROCKETMQ_UID $ROCKETMQ_GID 46 | 47 | echo "Changed hostPath $NAME_SERVER_DATA_PATH uid to $ROCKETMQ_UID, gid to $ROCKETMQ_GID" 48 | echo "Changed hostPath $BROKER_DATA_PATH uid to $ROCKETMQ_UID, gid to $ROCKETMQ_GID" 49 | echo "Changed hostPath $CONTROLLER_DATA_PATH uid to $ROCKETMQ_UID, gid to $ROCKETMQ_GID" 50 | -------------------------------------------------------------------------------- /deploy/storage/nfs-client-class.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: storage.k8s.io/v1 17 | kind: StorageClass 18 | metadata: 19 | name: rocketmq-storage 20 | provisioner: rocketmq/nfs 21 | -------------------------------------------------------------------------------- /deploy/storage/nfs-client-sa.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: v1 17 | kind: ServiceAccount 18 | metadata: 19 | name: nfs-client-provisioner 20 | 21 | --- 22 | kind: ClusterRole 23 | apiVersion: rbac.authorization.k8s.io/v1 24 | metadata: 25 | name: nfs-client-provisioner-runner 26 | rules: 27 | - apiGroups: [""] 28 | resources: ["persistentvolumes"] 29 | verbs: ["get", "list", "watch", "create", "delete"] 30 | - apiGroups: [""] 31 | resources: ["persistentvolumeclaims"] 32 | verbs: ["get", "list", "watch", "update"] 33 | - apiGroups: ["storage.k8s.io"] 34 | resources: ["storageclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: [""] 37 | resources: ["events"] 38 | verbs: ["list", "watch", "create", "update", "patch"] 39 | - apiGroups: [""] 40 | resources: ["endpoints"] 41 | verbs: ["create", "delete", "get", "list", "watch", "patch", "update"] 42 | 43 | --- 44 | kind: ClusterRoleBinding 45 | apiVersion: rbac.authorization.k8s.io/v1 46 | metadata: 47 | name: run-nfs-client-provisioner 48 | subjects: 49 | - kind: ServiceAccount 50 | name: nfs-client-provisioner 51 | namespace: default 52 | roleRef: 53 | kind: ClusterRole 54 | name: nfs-client-provisioner-runner 55 | apiGroup: rbac.authorization.k8s.io 56 | -------------------------------------------------------------------------------- /deploy/storage/nfs-client.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | kind: Deployment 17 | apiVersion: extensions/v1beta1 18 | metadata: 19 | name: nfs-client-provisioner 20 | spec: 21 | replicas: 1 22 | strategy: 23 | type: Recreate 24 | template: 25 | metadata: 26 | labels: 27 | app: nfs-client-provisioner 28 | spec: 29 | serviceAccountName: nfs-client-provisioner 30 | containers: 31 | - name: nfs-client-provisioner 32 | image: quay.io/external_storage/nfs-client-provisioner:latest 33 | volumeMounts: 34 | - name: nfs-client-root 35 | mountPath: /persistentvolumes 36 | env: 37 | - name: PROVISIONER_NAME 38 | value: rocketmq/nfs 39 | - name: NFS_SERVER 40 | value: 192.168.130.32 41 | - name: NFS_PATH 42 | value: /data/k8s 43 | volumes: 44 | - name: nfs-client-root 45 | nfs: 46 | server: 192.168.130.32 47 | path: /data/k8s 48 | -------------------------------------------------------------------------------- /deploy/storage/remove-storage-class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | kubectl delete -f nfs-client-sa.yaml 19 | kubectl delete -f nfs-client-class.yaml 20 | kubectl delete -f nfs-client.yaml 21 | -------------------------------------------------------------------------------- /docs/cn/nfs_install_cn.md: -------------------------------------------------------------------------------- 1 | ## NFS 存储服务部署 2 | 3 | 本文档将通过一个示例介绍如何简单地在您的Kubernetes集群上部署NFS共享存储服务。 4 | 5 | ### 安装 NFS 服务端 6 | 7 | 选择您的一个节点来安装 NFS 服务,假设我们的共享数据目录为:```/data/k8s``` 8 | 9 | 1. 关闭防火墙(需要sudo权限) 10 | 11 | ``` 12 | $ systemctl stop firewalld.service 13 | 14 | $ systemctl disable firewalld.service 15 | ``` 16 | 17 | 2. 安装配置 NFS 18 | 19 | ``` 20 | $ yum -y install nfs-utils rpcbind 21 | ``` 22 | 23 | 3. 设置共享目录的权限: 24 | 25 | ``` 26 | $ chmod 755 /data/k8s/ 27 | ``` 28 | 29 | 4. 配置 NFS,NFS 的默认配置文件在 ```/etc/exports``` 文件下,在该文件中添加下面的配置信息: 30 | 31 | ``` 32 | $ vi /etc/exports 33 | /data/k8s *(rw,sync,no_root_squash) 34 | ``` 35 | 36 | 5. 启动rpcbind服务 37 | 38 | ``` 39 | $ systemctl start rpcbind.service 40 | 41 | $ systemctl enable rpcbind 42 | 43 | $ systemctl status rpcbind 44 | ··· 45 | Sep 16 10:27:19 master systemd[1]: Started RPC bind service. 46 | ``` 47 | 48 | 如果看到上面的 Started 说明rpcbind启动成功了。 49 | 50 | 6. 启动 NFS 服务: 51 | 52 | ``` 53 | $ systemctl start nfs.service 54 | 55 | $ systemctl enable nfs 56 | 57 | $ systemctl status nfs 58 | ··· 59 | Sep 16 10:28:01 master systemd[1]: Started NFS server and services. 60 | ``` 61 | 62 | 如果看到上面的 Started 则说明 NFS Server 启动成功了。 63 | 64 | 也可以通过以下命令确认: 65 | 66 | ``` 67 | $ rpcinfo -p | grep nfs 68 | 100003 3 tcp 2049 nfs 69 | 100003 4 tcp 2049 nfs 70 | 100227 3 tcp 2049 nfs_acl 71 | 100003 3 udp 2049 nfs 72 | 100003 4 udp 2049 nfs 73 | 100227 3 udp 2049 nfs_acl 74 | ``` 75 | 76 | 到这里我们就安装好了 NFS server,接下来我们在其他节点上安装 NFS 的客户端。 77 | 78 | ### 安装 NFS 客户端 79 | 80 | 在您的Kubernetes集群每个节点上安装NFS: 81 | 82 | 1. 先关闭防火墙: 83 | 84 | ``` 85 | $ systemctl stop firewalld.service 86 | 87 | $ systemctl disable firewalld.service 88 | ``` 89 | 90 | 2. 安装 NFS 91 | 92 | ``` 93 | $ yum -y install nfs-utils rpcbind 94 | ``` 95 | 96 | 3. 与上面的方法一样,先启动 rpc、然后启动 NFS: 97 | ``` 98 | $ systemctl start rpcbind.service 99 | 100 | $ systemctl enable rpcbind.service 101 | 102 | $ systemctl start nfs.service 103 | 104 | $ systemctl enable nfs.service 105 | ``` 106 | 107 | 4. 客户端启动完成后,检查 NFS 是否有共享目录: 108 | 109 | ``` 110 | $ showmount -e 192.168.130.32 111 | Export list for 192.168.130.32: 112 | /data/k8s * 113 | ``` 114 | 115 | 其中```192.168.130.32```是您的NFS服务端所在的节点IP 116 | 117 | 进一步的验证操作请查看[NFS存储准备工作文档](README.md) 118 | 119 | -------------------------------------------------------------------------------- /docs/en/nfs_install_en.md: -------------------------------------------------------------------------------- 1 | ## Deploy NFS Service 2 | 3 | This document will show you how to simply deploy the NFS shared storage service on your Kubernetes cluster with an example. 4 | 5 | ### Install NFS Server 6 | 7 | Choose one of your nodes to install the NFS service, assuming our shared data directory is: ```/data/k8s``` 8 | 9 | 1. Turn off the firewall (requires sudo privileges) 10 | 11 | ``` 12 | $ systemctl stop firewalld.service 13 | 14 | $ systemctl disable firewalld.service 15 | ``` 16 | 17 | 2. Install and configure NFS 18 | 19 | ``` 20 | $ yum -y install nfs-utils rpcbind 21 | ``` 22 | 23 | 3. Set permissions for the shared directory: 24 | 25 | ``` 26 | $ chmod 755 /data/k8s/ 27 | ``` 28 | 29 | 4. Configure NFS. The default configuration file for NFS is under ```/etc/exports```. Add the following configuration information to the file: 30 | 31 | ``` 32 | $ vi /etc/exports 33 | /data/k8s *(rw,sync,no_root_squash) 34 | ``` 35 | 36 | 5. Start rpcbind service: 37 | 38 | ``` 39 | $ systemctl start rpcbind.service 40 | 41 | $ systemctl enable rpcbind 42 | 43 | $ systemctl status rpcbind 44 | ··· 45 | Sep 16 10:27:19 master systemd[1]: Started RPC bind service. 46 | ``` 47 | 48 | If you see the above output, the rpcbind is successfully started. 49 | 50 | 6. Start NFS service: 51 | 52 | ``` 53 | $ systemctl start nfs.service 54 | 55 | $ systemctl enable nfs 56 | 57 | $ systemctl status nfs 58 | ··· 59 | Sep 16 10:28:01 master systemd[1]: Started NFS server and services. 60 | ``` 61 | 62 | If you see the above output, the NFS server is successfully started. 63 | 64 | It can also be confirmed by the following command: 65 | 66 | ``` 67 | $ rpcinfo -p | grep nfs 68 | 100003 3 tcp 2049 nfs 69 | 100003 4 tcp 2049 nfs 70 | 100227 3 tcp 2049 nfs_acl 71 | 100003 3 udp 2049 nfs 72 | 100003 4 udp 2049 nfs 73 | 100227 3 udp 2049 nfs_acl 74 | ``` 75 | 76 | So here we have the NFS server installed, then we install the NFS service on the other nodes. 77 | 78 | ### Install NFS Clients 79 | 80 | Install NFS on the other nodes of your Kubernetes cluster: 81 | 82 | 1. Turn off the firewall first: 83 | 84 | ``` 85 | $ systemctl stop firewalld.service 86 | 87 | $ systemctl disable firewalld.service 88 | ``` 89 | 90 | 2. Install NFS 91 | 92 | ``` 93 | $ yum -y install nfs-utils rpcbind 94 | ``` 95 | 96 | 3. As with the above method, start rpc first, then start NFS: 97 | 98 | ``` 99 | $ systemctl start rpcbind.service 100 | 101 | $ systemctl enable rpcbind.service 102 | 103 | $ systemctl start nfs.service 104 | 105 | $ systemctl enable nfs.service 106 | ``` 107 | 108 | 4. After the client startup is complete, check if NFS has a shared directory: 109 | 110 | ``` 111 | $ showmount -e 192.168.130.32 112 | Export list for 192.168.130.32: 113 | /data/k8s * 114 | ``` 115 | 116 | Where ```192.168.130.32``` is the node IP where your NFS server is located. 117 | 118 | For further verification operations, please see [NFS Storage Preparation Document](../../README.md) 119 | -------------------------------------------------------------------------------- /docs/img/operator-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache/rocketmq-operator/03741c8521a8d5063a1d5c1d1d704f1072e9d767/docs/img/operator-arch.png -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_broker_cr.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: v1 17 | kind: ConfigMap 18 | metadata: 19 | name: broker-config 20 | data: 21 | BROKER_MEM: " -Xms2g -Xmx2g -Xmn1g " 22 | broker-common.conf: | 23 | # brokerClusterName, brokerName, brokerId are automatically generated by the operator and do not set it manually!!! 24 | deleteWhen=04 25 | fileReservedTime=48 26 | flushDiskType=ASYNC_FLUSH 27 | # set brokerRole to ASYNC_MASTER or SYNC_MASTER. DO NOT set to SLAVE because the replica instance will automatically be set!!! 28 | brokerRole=ASYNC_MASTER 29 | 30 | --- 31 | apiVersion: rocketmq.apache.org/v1alpha1 32 | kind: Broker 33 | metadata: 34 | # name of broker cluster 35 | name: broker 36 | spec: 37 | # size is the number of the broker cluster, each broker cluster contains a master broker and [replicaPerGroup] replica brokers. 38 | size: 1 39 | # nameServers is the [ip:port] list of name service 40 | nameServers: "" 41 | # replicaPerGroup is the number of each broker cluster 42 | replicaPerGroup: 1 43 | # brokerImage is the customized docker image repo of the RocketMQ broker 44 | brokerImage: apacherocketmq/rocketmq-broker:4.5.0-alpine-operator-0.3.0 45 | # imagePullPolicy is the image pull policy 46 | imagePullPolicy: Always 47 | # resources describes the compute resource requirements and limits 48 | resources: 49 | requests: 50 | memory: "2048Mi" 51 | cpu: "250m" 52 | limits: 53 | memory: "12288Mi" 54 | cpu: "500m" 55 | # allowRestart defines whether allow pod restart 56 | allowRestart: true 57 | # storageMode can be EmptyDir, HostPath, StorageClass 58 | storageMode: HostPath 59 | # hostPath is the local path to store data 60 | hostPath: /data/rocketmq/broker 61 | # scalePodName is [Broker name]-[broker group number]-master-0 62 | scalePodName: broker-0-master-0 63 | # env defines custom env, e.g. BROKER_MEM 64 | env: 65 | - name: BROKER_MEM 66 | valueFrom: 67 | configMapKeyRef: 68 | name: broker-config 69 | key: BROKER_MEM 70 | # volumes defines the broker.conf 71 | volumes: 72 | - name: broker-config 73 | configMap: 74 | name: broker-config 75 | items: 76 | - key: broker-common.conf 77 | path: broker-common.conf 78 | # volumeClaimTemplates defines the storageClass 79 | volumeClaimTemplates: 80 | - metadata: 81 | name: broker-storage 82 | annotations: 83 | volume.beta.kubernetes.io/storage-class: rocketmq-storage 84 | spec: 85 | accessModes: [ "ReadWriteOnce" ] 86 | resources: 87 | requests: 88 | storage: 8Gi 89 | -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_cluster_service.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: v1 17 | kind: Service 18 | metadata: 19 | name: console-service 20 | labels: 21 | app: rocketmq-console 22 | spec: 23 | type: NodePort 24 | selector: 25 | app: rocketmq-console 26 | ports: 27 | - port: 8080 28 | targetPort: 8080 29 | protocol: TCP 30 | nodePort: 30000 31 | --- 32 | #apiVersion: v1 33 | #kind: Service 34 | #metadata: 35 | # name: name-server-service 36 | # namespace: default 37 | #spec: 38 | # type: NodePort 39 | # selector: 40 | # name_service_cr: name-service 41 | # ports: 42 | # - port: 9876 43 | # targetPort: 9876 44 | # # use this port to access the name server cluster 45 | # nodePort: 30001 46 | #--- 47 | 48 | 49 | -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_console_cr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: console-config 5 | data: 6 | application.yml: | 7 | server: 8 | port: 8080 9 | servlet: 10 | encoding: 11 | charset: UTF-8 12 | enabled: true 13 | force: true 14 | spring: 15 | application: 16 | name: rocketmq-dashboard 17 | logging: 18 | config: classpath:logback.xml 19 | rocketmq: 20 | config: 21 | isVIPChannel: 22 | timeoutMillis: 23 | dataPath: /tmp/rocketmq-console/data 24 | enableDashBoardCollect: true 25 | msgTrackTopicName: 26 | ticketKey: ticket 27 | loginRequired: false 28 | useTLS: false 29 | threadpool: 30 | config: 31 | coreSize: 10 32 | maxSize: 10 33 | keepAliveTime: 3000 34 | queueSize: 5000 35 | role-permission.yml: | 36 | rolePerms: 37 | ordinary: 38 | - /rocketmq/*.query 39 | - /ops/*.query 40 | - /dashboard/*.query 41 | - /topic/*.query 42 | - /topic/sendTopicMessage.do 43 | - /producer/*.query 44 | - /message/*.query 45 | - /messageTrace/*.query 46 | - /monitor/*.query 47 | - /consumer/*.query 48 | - /cluster/*.query 49 | - /dlqMessage/*.query 50 | - /dlqMessage/exportDlqMessage.do 51 | - /dlqMessage/batchResendDlqMessage.do 52 | - /acl/*.query 53 | --- 54 | 55 | apiVersion: rocketmq.apache.org/v1alpha1 56 | kind: Console 57 | metadata: 58 | name: console 59 | namespace: default 60 | spec: 61 | # nameServers is the [ip:port] list of name service 62 | nameServers: "" 63 | # consoleDeployment define the console deployment 64 | consoleDeployment: 65 | apiVersion: apps/v1 66 | kind: Deployment 67 | metadata: 68 | labels: 69 | app: rocketmq-console 70 | spec: 71 | replicas: 1 72 | selector: 73 | matchLabels: 74 | app: rocketmq-console 75 | template: 76 | metadata: 77 | labels: 78 | app: rocketmq-console 79 | spec: 80 | containers: 81 | - name: console 82 | image: apacherocketmq/rocketmq-console:2.0.0 83 | args: ["--spring.config.location=/apps/data/console/config/"] 84 | ports: 85 | - containerPort: 8080 86 | volumeMounts: 87 | - mountPath: "/apps/data/console/config" 88 | name: console-config 89 | volumes: 90 | - name: console-config 91 | configMap: 92 | name: console-config -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_controller_cr.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: rocketmq.apache.org/v1alpha1 18 | kind: Controller 19 | metadata: 20 | # name of controller cluster 21 | name: controller 22 | spec: 23 | # size is the number of controllers. 24 | size: 1 25 | # controllerImage is the customized docker image repo of the RocketMQ Controller 26 | controllerImage: apacherocketmq/rocketmq-nameserver:5.0.0-alpine-operator-0.4.0 27 | # imagePullPolicy is the image pull policy 28 | imagePullPolicy: IfNotPresent 29 | # resources describes the compute resource requirements and limits 30 | resources: 31 | requests: 32 | memory: "2Gi" 33 | limits: 34 | memory: "2Gi" 35 | # storageMode can be EmptyDir, HostPath, StorageClass 36 | storageMode: HostPath 37 | # hostPath is the local path to store data 38 | hostPath: /data/rocketmq/controller 39 | # volumeClaimTemplates defines the storageClass 40 | volumeClaimTemplates: 41 | - metadata: 42 | name: controller-storage 43 | spec: 44 | accessModes: [ "ReadWriteOnce" ] 45 | resources: 46 | requests: 47 | storage: 8Gi 48 | -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_nameservice_cr.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: rocketmq.apache.org/v1alpha1 17 | kind: NameService 18 | metadata: 19 | name: name-service 20 | spec: 21 | # size is the the name service instance number of the name service cluster 22 | size: 1 23 | # nameServiceImage is the customized docker image repo of the RocketMQ name service 24 | nameServiceImage: apacherocketmq/rocketmq-nameserver:4.5.0-alpine-operator-0.3.0 25 | # imagePullPolicy is the image pull policy 26 | imagePullPolicy: Always 27 | # hostNetwork can be true or false 28 | hostNetwork: true 29 | # Set DNS policy for the pod. 30 | # Defaults to "ClusterFirst". 31 | # Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. 32 | # DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. 33 | # To have DNS options set along with hostNetwork, you have to specify DNS policy 34 | # explicitly to 'ClusterFirstWithHostNet'. 35 | dnsPolicy: ClusterFirstWithHostNet 36 | # resources describes the compute resource requirements and limits 37 | resources: 38 | requests: 39 | memory: "512Mi" 40 | cpu: "250m" 41 | limits: 42 | memory: "1024Mi" 43 | cpu: "500m" 44 | # storageMode can be EmptyDir, HostPath, StorageClass 45 | storageMode: HostPath 46 | # hostPath is the local path to store data 47 | hostPath: /data/rocketmq/nameserver 48 | # volumeClaimTemplates defines the storageClass 49 | volumeClaimTemplates: 50 | - metadata: 51 | name: namesrv-storage 52 | annotations: 53 | volume.beta.kubernetes.io/storage-class: rocketmq-storage 54 | spec: 55 | accessModes: [ "ReadWriteOnce" ] 56 | resources: 57 | requests: 58 | storage: 1Gi 59 | -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_rocketmq_cluster.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: v1 17 | kind: ConfigMap 18 | metadata: 19 | name: broker-config 20 | namespace: default 21 | data: 22 | # BROKER_MEM sets the broker JVM, if set to "" then Xms = Xmx = max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB)) 23 | BROKER_MEM: " -Xms2g -Xmx2g -Xmn1g " 24 | broker-common.conf: | 25 | # brokerClusterName, brokerName, brokerId are automatically generated by the operator and do not set it manually!!! 26 | deleteWhen=04 27 | fileReservedTime=48 28 | flushDiskType=ASYNC_FLUSH 29 | # set brokerRole to ASYNC_MASTER or SYNC_MASTER. DO NOT set to SLAVE because the replica instance will automatically be set!!! 30 | brokerRole=ASYNC_MASTER 31 | 32 | --- 33 | apiVersion: rocketmq.apache.org/v1alpha1 34 | kind: Broker 35 | metadata: 36 | # name of broker cluster 37 | name: broker 38 | namespace: default 39 | spec: 40 | # size is the number of the broker cluster, each broker cluster contains a master broker and [replicaPerGroup] replica brokers. 41 | size: 1 42 | # nameServers is the [ip:port] list of name service 43 | nameServers: "" 44 | # replicaPerGroup is the number of each broker cluster 45 | replicaPerGroup: 1 46 | # brokerImage is the customized docker image repo of the RocketMQ broker 47 | brokerImage: apacherocketmq/rocketmq-broker:4.5.0-alpine-operator-0.3.0 48 | # imagePullPolicy is the image pull policy 49 | imagePullPolicy: Always 50 | # resources describes the compute resource requirements and limits 51 | resources: 52 | requests: 53 | memory: "2048Mi" 54 | cpu: "250m" 55 | limits: 56 | memory: "12288Mi" 57 | cpu: "500m" 58 | # allowRestart defines whether allow pod restart 59 | allowRestart: true 60 | # storageMode can be EmptyDir, HostPath, StorageClass 61 | storageMode: EmptyDir 62 | # hostPath is the local path to store data 63 | hostPath: /data/rocketmq/broker 64 | # scalePodName is [Broker name]-[broker group number]-master-0 65 | scalePodName: broker-0-master-0 66 | # env defines custom env, e.g. BROKER_MEM 67 | env: 68 | - name: BROKER_MEM 69 | valueFrom: 70 | configMapKeyRef: 71 | name: broker-config 72 | key: BROKER_MEM 73 | # volumes defines the broker.conf 74 | volumes: 75 | - name: broker-config 76 | configMap: 77 | name: broker-config 78 | items: 79 | - key: broker-common.conf 80 | path: broker-common.conf 81 | # volumeClaimTemplates defines the storageClass 82 | volumeClaimTemplates: 83 | - metadata: 84 | name: broker-storage 85 | spec: 86 | accessModes: 87 | - ReadWriteOnce 88 | storageClassName: rocketmq-storage 89 | resources: 90 | requests: 91 | storage: 8Gi 92 | --- 93 | apiVersion: rocketmq.apache.org/v1alpha1 94 | kind: NameService 95 | metadata: 96 | name: name-service 97 | namespace: default 98 | spec: 99 | # size is the the name service instance number of the name service cluster 100 | size: 1 101 | # nameServiceImage is the customized docker image repo of the RocketMQ name service 102 | nameServiceImage: apacherocketmq/rocketmq-nameserver:4.5.0-alpine-operator-0.3.0 103 | # imagePullPolicy is the image pull policy 104 | imagePullPolicy: Always 105 | # hostNetwork can be true or false 106 | hostNetwork: true 107 | # Set DNS policy for the pod. 108 | # Defaults to "ClusterFirst". 109 | # Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. 110 | # DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. 111 | # To have DNS options set along with hostNetwork, you have to specify DNS policy 112 | # explicitly to 'ClusterFirstWithHostNet'. 113 | dnsPolicy: ClusterFirstWithHostNet 114 | # resources describes the compute resource requirements and limits 115 | resources: 116 | requests: 117 | memory: "512Mi" 118 | cpu: "250m" 119 | limits: 120 | memory: "1024Mi" 121 | cpu: "500m" 122 | # storageMode can be EmptyDir, HostPath, StorageClass 123 | storageMode: EmptyDir 124 | # hostPath is the local path to store data 125 | hostPath: /data/rocketmq/nameserver 126 | # volumeClaimTemplates defines the storageClass 127 | volumeClaimTemplates: 128 | - metadata: 129 | name: namesrv-storage 130 | spec: 131 | accessModes: 132 | - ReadWriteOnce 133 | storageClassName: rocketmq-storage 134 | resources: 135 | requests: 136 | storage: 1Gi 137 | 138 | --- 139 | apiVersion: rocketmq.apache.org/v1alpha1 140 | kind: Console 141 | metadata: 142 | name: console 143 | namespace: default 144 | spec: 145 | # nameServers is the [ip:port] list of name service 146 | nameServers: "" 147 | # consoleDeployment define the console deployment 148 | consoleDeployment: 149 | apiVersion: apps/v1 150 | kind: Deployment 151 | metadata: 152 | labels: 153 | app: rocketmq-console 154 | spec: 155 | replicas: 1 156 | selector: 157 | matchLabels: 158 | app: rocketmq-console 159 | template: 160 | metadata: 161 | labels: 162 | app: rocketmq-console 163 | spec: 164 | containers: 165 | - name: console 166 | image: apacherocketmq/rocketmq-console:2.0.0 167 | ports: 168 | - containerPort: 8080 -------------------------------------------------------------------------------- /example/rocketmq_v1alpha1_topictransfer_cr.yaml: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. 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 | apiVersion: rocketmq.apache.org/v1alpha1 17 | kind: TopicTransfer 18 | metadata: 19 | name: topictransfer 20 | spec: 21 | # topic defines which topic to be transferred 22 | topic: TopicTest 23 | # sourceCluster define the source cluster 24 | sourceCluster: broker-0 25 | # targetCluster defines the target cluster 26 | targetCluster: broker-1 27 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/apache/rocketmq-operator 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/google/uuid v1.1.2 7 | github.com/pkg/errors v0.9.1 8 | k8s.io/api v0.22.1 9 | k8s.io/apimachinery v0.22.1 10 | k8s.io/client-go v0.22.1 11 | sigs.k8s.io/controller-runtime v0.10.0 12 | ) 13 | 14 | replace github.com/apache/rocketmq-operator/ => ./ 15 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 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 | */ -------------------------------------------------------------------------------- /images/broker/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | FROM --platform=$TARGETPLATFORM openjdk:8-alpine 19 | 20 | RUN apk add --no-cache bash gettext nmap-ncat openssl busybox-extras 21 | 22 | ARG version 23 | 24 | # Rocketmq version 25 | ENV ROCKETMQ_VERSION ${version} 26 | 27 | # Rocketmq home 28 | ENV ROCKETMQ_HOME /root/rocketmq/broker 29 | 30 | WORKDIR ${ROCKETMQ_HOME} 31 | 32 | # Install 33 | RUN set -eux; \ 34 | apk add --virtual .build-deps curl gnupg unzip; \ 35 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip -o rocketmq.zip; \ 36 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip.asc -o rocketmq.zip.asc; \ 37 | curl -L https://www.apache.org/dist/rocketmq/KEYS -o KEYS; \ 38 | \ 39 | gpg --import KEYS; \ 40 | gpg --batch --verify rocketmq.zip.asc rocketmq.zip; \ 41 | unzip rocketmq.zip; \ 42 | mv rocketmq-all*/* . ; \ 43 | rmdir rocketmq-all* ; \ 44 | rm rocketmq.zip ; \ 45 | rm rocketmq.zip.asc KEYS; \ 46 | apk del .build-deps ; \ 47 | rm -rf /var/cache/apk/* ; \ 48 | rm -rf /tmp/* 49 | 50 | # Copy customized scripts 51 | COPY runbroker-customize.sh ${ROCKETMQ_HOME}/bin/ 52 | 53 | # Expose broker ports 54 | EXPOSE 10909 10911 10912 55 | 56 | # Override customized scripts for broker 57 | RUN mv ${ROCKETMQ_HOME}/bin/runbroker-customize.sh ${ROCKETMQ_HOME}/bin/runbroker.sh \ 58 | && chmod a+x ${ROCKETMQ_HOME}/bin/runbroker.sh \ 59 | && chmod a+x ${ROCKETMQ_HOME}/bin/mqbroker 60 | 61 | # Export Java options 62 | RUN export JAVA_OPT=" -Duser.home=/opt" 63 | 64 | # Add ${JAVA_HOME}/lib/ext as java.ext.dirs 65 | RUN sed -i 's/${JAVA_HOME}\/jre\/lib\/ext/${JAVA_HOME}\/jre\/lib\/ext:${JAVA_HOME}\/lib\/ext/' ${ROCKETMQ_HOME}/bin/tools.sh 66 | 67 | COPY brokerGenConfig.sh brokerStart.sh ${ROCKETMQ_HOME}/bin/ 68 | 69 | RUN chmod a+x ${ROCKETMQ_HOME}/bin/brokerGenConfig.sh \ 70 | && chmod a+x ${ROCKETMQ_HOME}/bin/brokerStart.sh 71 | 72 | WORKDIR ${ROCKETMQ_HOME}/bin 73 | 74 | CMD ["/bin/bash", "./brokerStart.sh"] 75 | -------------------------------------------------------------------------------- /images/broker/alpine/brokerGenConfig.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | BROKER_CONFIG_FILE="$ROCKETMQ_HOME/conf/broker.conf" 19 | BROKER_CONFIG_MOUNT_FILE="$ROCKETMQ_HOME/conf/broker-common.conf" 20 | 21 | function create_config() { 22 | rm -f $BROKER_CONFIG_FILE 23 | echo "Creating broker configuration." 24 | # Remove brokerClusterName, brokerName, brokerId if configured 25 | sed -e '/brokerClusterName/d;/brokerName/d;/brokerId/d' $BROKER_CONFIG_MOUNT_FILE > $BROKER_CONFIG_FILE 26 | echo -e >> $BROKER_CONFIG_FILE 27 | echo "brokerClusterName=$BROKER_CLUSTER_NAME" >> $BROKER_CONFIG_FILE 28 | echo "brokerName=$BROKER_NAME" >> $BROKER_CONFIG_FILE 29 | echo "brokerId=$BROKER_ID" >> $BROKER_CONFIG_FILE 30 | 31 | echo "brokerIP1=${POD_IP}" >> $BROKER_CONFIG_FILE 32 | if [ $BROKER_ID != 0 ]; then 33 | sed -i 's/brokerRole=.*/brokerRole=SLAVE/g' $BROKER_CONFIG_FILE 34 | fi 35 | 36 | if [ "${enableControllerMode}" = "true" ]; then 37 | echo "enableControllerMode=true" >> $BROKER_CONFIG_FILE 38 | echo "controllerAddr=${controllerAddr}" >> $BROKER_CONFIG_FILE 39 | fi 40 | } 41 | 42 | create_config 43 | cat $BROKER_CONFIG_FILE -------------------------------------------------------------------------------- /images/broker/alpine/brokerStart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | ./brokerGenConfig.sh 19 | ./mqbroker -n $NAMESRV_ADDR -c $ROCKETMQ_HOME/conf/broker.conf -------------------------------------------------------------------------------- /images/broker/alpine/build-broker-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | checkVersion() 19 | { 20 | echo "Version = $1" 21 | echo $1 |grep -E "^[0-9]+\.[0-9]+\.[0-9]+" > /dev/null 22 | if [ $? = 0 ]; then 23 | return 1 24 | fi 25 | 26 | echo "Version $1 illegal, it should be X.X.X format(e.g. 4.5.0), please check released versions in 'https://dist.apache.org/repos/dist/release/rocketmq/'" 27 | exit 2 28 | } 29 | 30 | if [ $# -lt 1 ]; then 31 | echo -e "Usage: sh $0 Version" 32 | exit 2 33 | fi 34 | 35 | ROCKETMQ_VERSION=$1 36 | DOCKERHUB_REPO=apacherocketmq/rocketmq-broker 37 | IMAGE_NAME=${DOCKERHUB_REPO}:${ROCKETMQ_VERSION}-alpine-operator-0.4.0 38 | 39 | checkVersion $ROCKETMQ_VERSION 40 | 41 | docker buildx build --platform linux/amd64 --load -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 42 | #docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 43 | 44 | #docker push $IMAGE_NAME -------------------------------------------------------------------------------- /images/broker/alpine/runbroker-customize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | #=========================================================================================== 19 | # Java Environment Setting 20 | #=========================================================================================== 21 | error_exit () 22 | { 23 | echo "ERROR: $1 !!" 24 | exit 1 25 | } 26 | 27 | find_java_home() 28 | { 29 | case "`uname`" in 30 | Darwin) 31 | JAVA_HOME=$(/usr/libexec/java_home) 32 | ;; 33 | *) 34 | JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac)))) 35 | ;; 36 | esac 37 | } 38 | 39 | find_java_home 40 | 41 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 42 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 43 | [ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!" 44 | 45 | export JAVA_HOME 46 | export JAVA="$JAVA_HOME/bin/java" 47 | export BASE_DIR=$(dirname $0)/.. 48 | export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} 49 | 50 | #=========================================================================================== 51 | # JVM Configuration 52 | #=========================================================================================== 53 | calculate_heap_sizes() 54 | { 55 | case "`uname`" in 56 | Linux) 57 | system_memory_in_mb=`free -m| sed -n '2p' | awk '{print $2}'` 58 | if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 59 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)/1024/1024)) 60 | elif [ -f /sys/fs/cgroup/memory.max ]; then 61 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory.max)/1024/1024)) 62 | else 63 | error_exit "Can not get memory, please check cgroup" 64 | fi 65 | if [ $system_memory_in_mb_in_docker -lt $system_memory_in_mb ];then 66 | system_memory_in_mb=$system_memory_in_mb_in_docker 67 | fi 68 | 69 | system_cpu_cores=`egrep -c 'processor([[:space:]]+):.*' /proc/cpuinfo` 70 | if [ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us ]; then 71 | system_cpu_cores_in_docker=$(($(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)/$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us))) 72 | elif [ -f /sys/fs/cgroup/cpu.max ]; then 73 | QUOTA=$(cut -d ' ' -f 1 /sys/fs/cgroup/cpu.max) 74 | PERIOD=$(cut -d ' ' -f 2 /sys/fs/cgroup/cpu.max) 75 | if [ "$QUOTA" == "max" ]; then # no limit, see https://docs.kernel.org/admin-guide/cgroup-v2.html#cgroup-v2-cpu 76 | system_cpu_cores_in_docker=$system_cpu_cores 77 | else 78 | system_cpu_cores_in_docker=$(($QUOTA/$PERIOD)) 79 | fi 80 | else 81 | error_exit "Can not get cpu, please check cgroup" 82 | fi 83 | if [ $system_cpu_cores_in_docker -lt $system_cpu_cores -a $system_cpu_cores_in_docker -ne 0 ];then 84 | system_cpu_cores=$system_cpu_cores_in_docker 85 | fi 86 | ;; 87 | FreeBSD) 88 | system_memory_in_bytes=`sysctl hw.physmem | awk '{print $2}'` 89 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 90 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 91 | ;; 92 | SunOS) 93 | system_memory_in_mb=`prtconf | awk '/Memory size:/ {print $3}'` 94 | system_cpu_cores=`psrinfo | wc -l` 95 | ;; 96 | Darwin) 97 | system_memory_in_bytes=`sysctl hw.memsize | awk '{print $2}'` 98 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 99 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 100 | ;; 101 | *) 102 | # assume reasonable defaults for e.g. a modern desktop or 103 | # cheap server 104 | system_memory_in_mb="2048" 105 | system_cpu_cores="2" 106 | ;; 107 | esac 108 | 109 | # some systems like the raspberry pi don't report cores, use at least 1 110 | if [ "$system_cpu_cores" -lt "1" ] 111 | then 112 | system_cpu_cores="1" 113 | fi 114 | 115 | # set max heap size based on the following 116 | # max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB)) 117 | # calculate 1/2 ram and cap to 1024MB 118 | # calculate 1/4 ram and cap to 8192MB 119 | # pick the max 120 | half_system_memory_in_mb=`expr $system_memory_in_mb / 2` 121 | quarter_system_memory_in_mb=`expr $half_system_memory_in_mb / 2` 122 | if [ "$half_system_memory_in_mb" -gt "1024" ] 123 | then 124 | half_system_memory_in_mb="1024" 125 | fi 126 | if [ "$quarter_system_memory_in_mb" -gt "8192" ] 127 | then 128 | quarter_system_memory_in_mb="8192" 129 | fi 130 | if [ "$half_system_memory_in_mb" -gt "$quarter_system_memory_in_mb" ] 131 | then 132 | max_heap_size_in_mb="$half_system_memory_in_mb" 133 | else 134 | max_heap_size_in_mb="$quarter_system_memory_in_mb" 135 | fi 136 | MAX_HEAP_SIZE="${max_heap_size_in_mb}M" 137 | 138 | # Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4 * heap size) 139 | max_sensible_yg_per_core_in_mb="100" 140 | max_sensible_yg_in_mb=`expr $max_sensible_yg_per_core_in_mb "*" $system_cpu_cores` 141 | 142 | desired_yg_in_mb=`expr $max_heap_size_in_mb / 4` 143 | 144 | if [ "$desired_yg_in_mb" -gt "$max_sensible_yg_in_mb" ] 145 | then 146 | HEAP_NEWSIZE="${max_sensible_yg_in_mb}M" 147 | else 148 | HEAP_NEWSIZE="${desired_yg_in_mb}M" 149 | fi 150 | } 151 | 152 | calculate_heap_sizes 153 | 154 | # Dynamically calculate parameters, for reference. 155 | Xms=$MAX_HEAP_SIZE 156 | Xmx=$MAX_HEAP_SIZE 157 | Xmn=$HEAP_NEWSIZE 158 | MaxDirectMemorySize=$MAX_HEAP_SIZE 159 | # Set for `JAVA_OPT`. 160 | JAVA_OPT="${JAVA_OPT} -server ${BROKER_MEM:-"-Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}"} " 161 | JAVA_OPT="${JAVA_OPT} -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30 -XX:SoftRefLRUPolicyMSPerMB=0 -XX:SurvivorRatio=8" 162 | JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/mq_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintAdaptiveSizePolicy" 163 | JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m" 164 | JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" 165 | JAVA_OPT="${JAVA_OPT} -XX:+AlwaysPreTouch" 166 | JAVA_OPT="${JAVA_OPT} -XX:MaxDirectMemorySize=${MaxDirectMemorySize}" 167 | JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages -XX:-UseBiasedLocking" 168 | JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" 169 | #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" 170 | JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" 171 | JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 172 | 173 | numactl --interleave=all pwd > /dev/null 2>&1 174 | if [ $? -eq 0 ] 175 | then 176 | if [ -z "$RMQ_NUMA_NODE" ] ; then 177 | numactl --interleave=all $JAVA ${JAVA_OPT} $@ 178 | else 179 | numactl --cpunodebind=$RMQ_NUMA_NODE --membind=$RMQ_NUMA_NODE $JAVA ${JAVA_OPT} $@ 180 | fi 181 | else 182 | $JAVA ${JAVA_OPT} $@ 183 | fi 184 | -------------------------------------------------------------------------------- /images/controller/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | FROM --platform=$TARGETPLATFORM openjdk:8-alpine 19 | 20 | RUN apk add --no-cache bash gettext nmap-ncat openssl busybox-extras 21 | 22 | ARG version 23 | 24 | # Rocketmq version 25 | ENV ROCKETMQ_VERSION ${version} 26 | 27 | # Rocketmq home 28 | ENV ROCKETMQ_HOME /root/rocketmq/controller 29 | 30 | WORKDIR ${ROCKETMQ_HOME} 31 | 32 | # Install 33 | RUN set -eux; \ 34 | apk add --virtual .build-deps curl gnupg unzip; \ 35 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip -o rocketmq.zip; \ 36 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip.asc -o rocketmq.zip.asc; \ 37 | curl -L https://www.apache.org/dist/rocketmq/KEYS -o KEYS; \ 38 | gpg --import KEYS; \ 39 | gpg --batch --verify rocketmq.zip.asc rocketmq.zip; \ 40 | unzip rocketmq.zip; \ 41 | mv rocketmq-all*/* . ; \ 42 | rmdir rocketmq-all* ; \ 43 | rm rocketmq.zip ; \ 44 | rm rocketmq.zip.asc KEYS; \ 45 | apk del .build-deps ; \ 46 | rm -rf /var/cache/apk/* ; \ 47 | rm -rf /tmp/* 48 | 49 | # Copy customized scripts 50 | COPY runserver-customize.sh ${ROCKETMQ_HOME}/bin/ 51 | 52 | # Expose controller port 53 | EXPOSE 9878 54 | 55 | # Override customized scripts for controller 56 | # Export Java options 57 | # Add ${JAVA_HOME}/lib/ext as java.ext.dirs 58 | RUN mv ${ROCKETMQ_HOME}/bin/runserver-customize.sh ${ROCKETMQ_HOME}/bin/runserver.sh \ 59 | && chmod a+x ${ROCKETMQ_HOME}/bin/runserver.sh \ 60 | && chmod a+x ${ROCKETMQ_HOME}/bin/mqnamesrv \ 61 | && export JAVA_OPT=" -Duser.home=/opt" \ 62 | && sed -i 's/${JAVA_HOME}\/jre\/lib\/ext/${JAVA_HOME}\/jre\/lib\/ext:${JAVA_HOME}\/lib\/ext/' ${ROCKETMQ_HOME}/bin/tools.sh 63 | 64 | WORKDIR ${ROCKETMQ_HOME}/bin 65 | 66 | CMD /bin/bash ./mqcontroller -c ${ROCKETMQ_HOME}/conf/controller/controller.conf 67 | -------------------------------------------------------------------------------- /images/controller/alpine/build-controller-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | checkVersion() 19 | { 20 | echo "Version = $1" 21 | echo $1 |grep -E "^[0-9]+\.[0-9]+\.[0-9]+" > /dev/null 22 | if [ $? = 0 ]; then 23 | return 1 24 | fi 25 | 26 | echo "Version $1 illegal, it should be X.X.X format(e.g. 4.5.0), please check released versions in 'https://dist.apache.org/repos/dist/release/rocketmq/'" 27 | exit 2 28 | } 29 | 30 | if [ $# -lt 1 ]; then 31 | echo -e "Usage: sh $0 Version" 32 | exit 2 33 | fi 34 | 35 | ROCKETMQ_VERSION=$1 36 | DOCKERHUB_REPO=apacherocketmq/rocketmq-controller 37 | IMAGE_NAME=${DOCKERHUB_REPO}:${ROCKETMQ_VERSION}-alpine-operator-0.4.0 38 | 39 | checkVersion $ROCKETMQ_VERSION 40 | 41 | docker buildx build --platform linux/amd64 --load -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 42 | #docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 43 | 44 | #docker push $IMAGE_NAME -------------------------------------------------------------------------------- /images/controller/alpine/runserver-customize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | #=========================================================================================== 19 | # Java Environment Setting 20 | #=========================================================================================== 21 | error_exit () 22 | { 23 | echo "ERROR: $1 !!" 24 | exit 1 25 | } 26 | 27 | find_java_home() 28 | { 29 | case "`uname`" in 30 | Darwin) 31 | JAVA_HOME=$(/usr/libexec/java_home) 32 | ;; 33 | *) 34 | JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac)))) 35 | ;; 36 | esac 37 | } 38 | 39 | find_java_home 40 | 41 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 42 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 43 | [ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!" 44 | 45 | export JAVA_HOME 46 | export JAVA="$JAVA_HOME/bin/java" 47 | export BASE_DIR=$(dirname $0)/.. 48 | export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} 49 | 50 | #=========================================================================================== 51 | # JVM Configuration 52 | #=========================================================================================== 53 | calculate_heap_sizes() 54 | { 55 | case "`uname`" in 56 | Linux) 57 | system_memory_in_mb=`free -m| sed -n '2p' | awk '{print $2}'` 58 | if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 59 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)/1024/1024)) 60 | elif [ -f /sys/fs/cgroup/memory.max ]; then 61 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory.max)/1024/1024)) 62 | else 63 | error_exit "Can not get memory, please check cgroup" 64 | fi 65 | if [ $system_memory_in_mb_in_docker -lt $system_memory_in_mb ];then 66 | system_memory_in_mb=$system_memory_in_mb_in_docker 67 | fi 68 | system_cpu_cores=`egrep -c 'processor([[:space:]]+):.*' /proc/cpuinfo` 69 | if [ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us ]; then 70 | system_cpu_cores_in_docker=$(($(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)/$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us))) 71 | elif [ -f /sys/fs/cgroup/cpu.max ]; then 72 | QUOTA=$(cut -d ' ' -f 1 /sys/fs/cgroup/cpu.max) 73 | PERIOD=$(cut -d ' ' -f 2 /sys/fs/cgroup/cpu.max) 74 | if [ "$QUOTA" == "max" ]; then # no limit, see https://docs.kernel.org/admin-guide/cgroup-v2.html#cgroup-v2-cpu 75 | system_cpu_cores_in_docker=$system_cpu_cores 76 | else 77 | system_cpu_cores_in_docker=$(($QUOTA/$PERIOD)) 78 | fi 79 | else 80 | error_exit "Can not get cpu, please check cgroup" 81 | fi 82 | if [ $system_cpu_cores_in_docker -lt $system_cpu_cores -a $system_cpu_cores_in_docker -ne 0 ];then 83 | system_cpu_cores=$system_cpu_cores_in_docker 84 | fi 85 | ;; 86 | FreeBSD) 87 | system_memory_in_bytes=`sysctl hw.physmem | awk '{print $2}'` 88 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 89 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 90 | ;; 91 | SunOS) 92 | system_memory_in_mb=`prtconf | awk '/Memory size:/ {print $3}'` 93 | system_cpu_cores=`psrinfo | wc -l` 94 | ;; 95 | Darwin) 96 | system_memory_in_bytes=`sysctl hw.memsize | awk '{print $2}'` 97 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 98 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 99 | ;; 100 | *) 101 | # assume reasonable defaults for e.g. a modern desktop or 102 | # cheap server 103 | system_memory_in_mb="2048" 104 | system_cpu_cores="2" 105 | ;; 106 | esac 107 | 108 | # some systems like the raspberry pi don't report cores, use at least 1 109 | if [ "$system_cpu_cores" -lt "1" ] 110 | then 111 | system_cpu_cores="1" 112 | fi 113 | 114 | # set max heap size based on the following 115 | # max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB)) 116 | # calculate 1/2 ram and cap to 1024MB 117 | # calculate 1/4 ram and cap to 8192MB 118 | # pick the max 119 | half_system_memory_in_mb=`expr $system_memory_in_mb / 2` 120 | quarter_system_memory_in_mb=`expr $half_system_memory_in_mb / 2` 121 | if [ "$half_system_memory_in_mb" -gt "1024" ] 122 | then 123 | half_system_memory_in_mb="1024" 124 | fi 125 | if [ "$quarter_system_memory_in_mb" -gt "8192" ] 126 | then 127 | quarter_system_memory_in_mb="8192" 128 | fi 129 | if [ "$half_system_memory_in_mb" -gt "$quarter_system_memory_in_mb" ] 130 | then 131 | max_heap_size_in_mb="$half_system_memory_in_mb" 132 | else 133 | max_heap_size_in_mb="$quarter_system_memory_in_mb" 134 | fi 135 | MAX_HEAP_SIZE="${max_heap_size_in_mb}M" 136 | 137 | # Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4 * heap size) 138 | max_sensible_yg_per_core_in_mb="100" 139 | max_sensible_yg_in_mb=`expr $max_sensible_yg_per_core_in_mb "*" $system_cpu_cores` 140 | 141 | desired_yg_in_mb=`expr $max_heap_size_in_mb / 4` 142 | 143 | if [ "$desired_yg_in_mb" -gt "$max_sensible_yg_in_mb" ] 144 | then 145 | HEAP_NEWSIZE="${max_sensible_yg_in_mb}M" 146 | else 147 | HEAP_NEWSIZE="${desired_yg_in_mb}M" 148 | fi 149 | } 150 | 151 | calculate_heap_sizes 152 | 153 | # Dynamically calculate parameters, for reference. 154 | Xms=$MAX_HEAP_SIZE 155 | Xmx=$MAX_HEAP_SIZE 156 | Xmn=$HEAP_NEWSIZE 157 | 158 | # For controller deployed in K8s 159 | if test -n "$MY_POD_NAME" ;then 160 | echo "MY_POD_NAME=$MY_POD_NAME" 161 | controllerDLegerSelfIdValue=$(echo "$MY_POD_NAME" | tr -d -) 162 | export controllerDLegerSelfId=$controllerDLegerSelfIdValue 163 | fi 164 | 165 | # Set for `JAVA_OPT`. 166 | JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}" 167 | JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC" 168 | JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/rmq_srv_gc.log -XX:+PrintGCDetails" 169 | JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" 170 | JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages" 171 | JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" 172 | JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" 173 | JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 174 | 175 | echo "=============env beg=============" 176 | env 177 | echo "=============env end=============" 178 | 179 | #TODO cp from config map 180 | cp ${ROCKETMQ_HOME}/conf/controller/controller-standalone.conf ${ROCKETMQ_HOME}/conf/controller/controller.conf 181 | 182 | 183 | sed -i "s/^controllerDLegerGroup.*$/controllerDLegerGroup=${controllerDLegerGroup}/" ${ROCKETMQ_HOME}/conf/controller/controller.conf 184 | 185 | sed -i "s/^controllerDLegerPeers.*$/controllerDLegerPeers=${controllerDLegerPeers}/" ${ROCKETMQ_HOME}/conf/controller/controller.conf 186 | 187 | sed -i "s/^controllerDLegerSelfId.*$/controllerDLegerSelfId=${controllerDLegerSelfId}/" ${ROCKETMQ_HOME}/conf/controller/controller.conf 188 | 189 | #perl not exists, sed can't process 190 | #perl -pi -e "s|controllerStorePath.*$|controllerStorePath=${controllerStorePath}|g" ${ROCKETMQ_HOME}/conf/controller/controller.conf 191 | echo "" >> ${ROCKETMQ_HOME}/conf/controller/controller.conf 192 | echo "controllerStorePath=${controllerStorePath}" >> ${ROCKETMQ_HOME}/conf/controller/controller.conf 193 | 194 | $JAVA ${JAVA_OPT} $@ 195 | -------------------------------------------------------------------------------- /images/namesrv/alpine/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | FROM --platform=$TARGETPLATFORM openjdk:8-alpine 19 | 20 | RUN apk add --no-cache bash gettext nmap-ncat openssl busybox-extras 21 | 22 | ARG version 23 | 24 | # Rocketmq version 25 | ENV ROCKETMQ_VERSION ${version} 26 | 27 | # Rocketmq home 28 | ENV ROCKETMQ_HOME /root/rocketmq/nameserver 29 | 30 | WORKDIR ${ROCKETMQ_HOME} 31 | 32 | # Install 33 | RUN set -eux; \ 34 | apk add --virtual .build-deps curl gnupg unzip; \ 35 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip -o rocketmq.zip; \ 36 | curl https://archive.apache.org/dist/rocketmq/${ROCKETMQ_VERSION}/rocketmq-all-${ROCKETMQ_VERSION}-bin-release.zip.asc -o rocketmq.zip.asc; \ 37 | curl -L https://www.apache.org/dist/rocketmq/KEYS -o KEYS; \ 38 | gpg --import KEYS; \ 39 | gpg --batch --verify rocketmq.zip.asc rocketmq.zip; \ 40 | unzip rocketmq.zip; \ 41 | mv rocketmq-all*/* . ; \ 42 | rmdir rocketmq-all* ; \ 43 | rm rocketmq.zip ; \ 44 | rm rocketmq.zip.asc KEYS; \ 45 | apk del .build-deps ; \ 46 | rm -rf /var/cache/apk/* ; \ 47 | rm -rf /tmp/* 48 | 49 | # Copy customized scripts 50 | COPY runserver-customize.sh ${ROCKETMQ_HOME}/bin/ 51 | 52 | # Expose namesrv port 53 | EXPOSE 9876 54 | 55 | # Override customized scripts for namesrv 56 | # Export Java options 57 | # Add ${JAVA_HOME}/lib/ext as java.ext.dirs 58 | RUN mv ${ROCKETMQ_HOME}/bin/runserver-customize.sh ${ROCKETMQ_HOME}/bin/runserver.sh \ 59 | && chmod a+x ${ROCKETMQ_HOME}/bin/runserver.sh \ 60 | && chmod a+x ${ROCKETMQ_HOME}/bin/mqnamesrv \ 61 | && export JAVA_OPT=" -Duser.home=/opt" \ 62 | && sed -i 's/${JAVA_HOME}\/jre\/lib\/ext/${JAVA_HOME}\/jre\/lib\/ext:${JAVA_HOME}\/lib\/ext/' ${ROCKETMQ_HOME}/bin/tools.sh 63 | 64 | WORKDIR ${ROCKETMQ_HOME}/bin 65 | 66 | CMD ["/bin/bash", "mqnamesrv"] 67 | -------------------------------------------------------------------------------- /images/namesrv/alpine/build-namesrv-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | checkVersion() 19 | { 20 | echo "Version = $1" 21 | echo $1 |grep -E "^[0-9]+\.[0-9]+\.[0-9]+" > /dev/null 22 | if [ $? = 0 ]; then 23 | return 1 24 | fi 25 | 26 | echo "Version $1 illegal, it should be X.X.X format(e.g. 4.5.0), please check released versions in 'https://dist.apache.org/repos/dist/release/rocketmq/'" 27 | exit 2 28 | } 29 | 30 | if [ $# -lt 1 ]; then 31 | echo -e "Usage: sh $0 Version" 32 | exit 2 33 | fi 34 | 35 | ROCKETMQ_VERSION=$1 36 | DOCKERHUB_REPO=apacherocketmq/rocketmq-nameserver 37 | IMAGE_NAME=${DOCKERHUB_REPO}:${ROCKETMQ_VERSION}-alpine-operator-0.4.0 38 | 39 | checkVersion $ROCKETMQ_VERSION 40 | 41 | docker buildx build --platform linux/amd64 --load -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 42 | #docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAME} --build-arg version=${ROCKETMQ_VERSION} . 43 | 44 | #docker push $IMAGE_NAME -------------------------------------------------------------------------------- /images/namesrv/alpine/runserver-customize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | #=========================================================================================== 19 | # Java Environment Setting 20 | #=========================================================================================== 21 | error_exit () 22 | { 23 | echo "ERROR: $1 !!" 24 | exit 1 25 | } 26 | 27 | find_java_home() 28 | { 29 | case "`uname`" in 30 | Darwin) 31 | JAVA_HOME=$(/usr/libexec/java_home) 32 | ;; 33 | *) 34 | JAVA_HOME=$(dirname $(dirname $(readlink -f $(which javac)))) 35 | ;; 36 | esac 37 | } 38 | 39 | find_java_home 40 | 41 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java 42 | [ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java 43 | [ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!" 44 | 45 | export JAVA_HOME 46 | export JAVA="$JAVA_HOME/bin/java" 47 | export BASE_DIR=$(dirname $0)/.. 48 | export CLASSPATH=.:${BASE_DIR}/conf:${CLASSPATH} 49 | 50 | #=========================================================================================== 51 | # JVM Configuration 52 | #=========================================================================================== 53 | calculate_heap_sizes() 54 | { 55 | case "`uname`" in 56 | Linux) 57 | system_memory_in_mb=`free -m| sed -n '2p' | awk '{print $2}'` 58 | if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then 59 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)/1024/1024)) 60 | elif [ -f /sys/fs/cgroup/memory.max ]; then 61 | system_memory_in_mb_in_docker=$(($(cat /sys/fs/cgroup/memory.max)/1024/1024)) 62 | else 63 | error_exit "Can not get memory, please check cgroup" 64 | fi 65 | if [ $system_memory_in_mb_in_docker -lt $system_memory_in_mb ];then 66 | system_memory_in_mb=$system_memory_in_mb_in_docker 67 | fi 68 | 69 | system_cpu_cores=`egrep -c 'processor([[:space:]]+):.*' /proc/cpuinfo` 70 | if [ -f /sys/fs/cgroup/cpu/cpu.cfs_quota_us ]; then 71 | system_cpu_cores_in_docker=$(($(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)/$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us))) 72 | elif [ -f /sys/fs/cgroup/cpu.max ]; then 73 | QUOTA=$(cut -d ' ' -f 1 /sys/fs/cgroup/cpu.max) 74 | PERIOD=$(cut -d ' ' -f 2 /sys/fs/cgroup/cpu.max) 75 | if [ "$QUOTA" == "max" ]; then # no limit, see https://docs.kernel.org/admin-guide/cgroup-v2.html#cgroup-v2-cpu 76 | system_cpu_cores_in_docker=$system_cpu_cores 77 | else 78 | system_cpu_cores_in_docker=$(($QUOTA/$PERIOD)) 79 | fi 80 | else 81 | error_exit "Can not get cpu, please check cgroup" 82 | fi 83 | if [ $system_cpu_cores_in_docker -lt $system_cpu_cores -a $system_cpu_cores_in_docker -ne 0 ];then 84 | system_cpu_cores=$system_cpu_cores_in_docker 85 | fi 86 | ;; 87 | FreeBSD) 88 | system_memory_in_bytes=`sysctl hw.physmem | awk '{print $2}'` 89 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 90 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 91 | ;; 92 | SunOS) 93 | system_memory_in_mb=`prtconf | awk '/Memory size:/ {print $3}'` 94 | system_cpu_cores=`psrinfo | wc -l` 95 | ;; 96 | Darwin) 97 | system_memory_in_bytes=`sysctl hw.memsize | awk '{print $2}'` 98 | system_memory_in_mb=`expr $system_memory_in_bytes / 1024 / 1024` 99 | system_cpu_cores=`sysctl hw.ncpu | awk '{print $2}'` 100 | ;; 101 | *) 102 | # assume reasonable defaults for e.g. a modern desktop or 103 | # cheap server 104 | system_memory_in_mb="2048" 105 | system_cpu_cores="2" 106 | ;; 107 | esac 108 | 109 | # some systems like the raspberry pi don't report cores, use at least 1 110 | if [ "$system_cpu_cores" -lt "1" ] 111 | then 112 | system_cpu_cores="1" 113 | fi 114 | 115 | # set max heap size based on the following 116 | # max(min(1/2 ram, 1024MB), min(1/4 ram, 8GB)) 117 | # calculate 1/2 ram and cap to 1024MB 118 | # calculate 1/4 ram and cap to 8192MB 119 | # pick the max 120 | half_system_memory_in_mb=`expr $system_memory_in_mb / 2` 121 | quarter_system_memory_in_mb=`expr $half_system_memory_in_mb / 2` 122 | if [ "$half_system_memory_in_mb" -gt "1024" ] 123 | then 124 | half_system_memory_in_mb="1024" 125 | fi 126 | if [ "$quarter_system_memory_in_mb" -gt "8192" ] 127 | then 128 | quarter_system_memory_in_mb="8192" 129 | fi 130 | if [ "$half_system_memory_in_mb" -gt "$quarter_system_memory_in_mb" ] 131 | then 132 | max_heap_size_in_mb="$half_system_memory_in_mb" 133 | else 134 | max_heap_size_in_mb="$quarter_system_memory_in_mb" 135 | fi 136 | MAX_HEAP_SIZE="${max_heap_size_in_mb}M" 137 | 138 | # Young gen: min(max_sensible_per_modern_cpu_core * num_cores, 1/4 * heap size) 139 | max_sensible_yg_per_core_in_mb="100" 140 | max_sensible_yg_in_mb=`expr $max_sensible_yg_per_core_in_mb "*" $system_cpu_cores` 141 | 142 | desired_yg_in_mb=`expr $max_heap_size_in_mb / 4` 143 | 144 | if [ "$desired_yg_in_mb" -gt "$max_sensible_yg_in_mb" ] 145 | then 146 | HEAP_NEWSIZE="${max_sensible_yg_in_mb}M" 147 | else 148 | HEAP_NEWSIZE="${desired_yg_in_mb}M" 149 | fi 150 | } 151 | 152 | calculate_heap_sizes 153 | 154 | # Dynamically calculate parameters, for reference. 155 | Xms=$MAX_HEAP_SIZE 156 | Xmx=$MAX_HEAP_SIZE 157 | Xmn=$HEAP_NEWSIZE 158 | 159 | # For controller deployed in K8s 160 | if test -n "$MY_POD_NAME" ;then 161 | echo "MY_POD_NAME=$MY_POD_NAME" 162 | controllerDLegerSelfIdValue=$(echo "$MY_POD_NAME" | tr -d -) 163 | export controllerDLegerSelfId=$controllerDLegerSelfIdValue 164 | fi 165 | 166 | # Set for `JAVA_OPT`. 167 | JAVA_OPT="${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn}" 168 | JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC" 169 | JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/dev/shm/rmq_srv_gc.log -XX:+PrintGCDetails" 170 | JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" 171 | JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages" 172 | JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" 173 | #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" 174 | JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" 175 | JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" 176 | 177 | $JAVA ${JAVA_OPT} $@ 178 | -------------------------------------------------------------------------------- /images/try-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | NAMESRV_DOCKERHUB_REPO=apacherocketmq/rocketmq-nameserver 19 | BROKER_DOCKERHUB_REPO=apacherocketmq/rocketmq-broker 20 | ROCKETMQ_VERSION=4.5.0 21 | 22 | start_namesrv_broker() 23 | { 24 | TAG_SUFFIX=$1 25 | # Start nameserver 26 | docker run -d -v `pwd`/data/namesrv/logs:/home/rocketmq/logs -v `pwd`/data/namesrv/store:/home/rocketmq/store --name rmqnamesrv ${NAMESRV_DOCKERHUB_REPO}:${ROCKETMQ_VERSION}${TAG_SUFFIX} 27 | # Start Broker 28 | docker run -d -v `pwd`/data/broker/logs:/home/rocketmq/logs -v `pwd`/data/broker/store:/home/rocketmq/store --name rmqbroker --link rmqnamesrv:namesrv -e "NAMESRV_ADDR=namesrv:9876" ${BROKER_DOCKERHUB_REPO}:${ROCKETMQ_VERSION}${TAG_SUFFIX} 29 | } 30 | 31 | #if [ $# -lt 1 ]; then 32 | # echo -e "Usage: sh $0 BaseImage" 33 | # exit 2 34 | #fi 35 | 36 | export BASE_IMAGE=alpine 37 | 38 | RMQ_CONTAINER=$(docker ps -a|awk '/rmq/ {print $1}') 39 | if [[ -n "$RMQ_CONTAINER" ]]; then 40 | echo "Removing RocketMQ Container..." 41 | docker rm -fv $RMQ_CONTAINER 42 | # Wait till the existing containers are removed 43 | sleep 5 44 | fi 45 | 46 | if [ ! -d "`pwd`/data" ]; then 47 | mkdir -p "data" 48 | fi 49 | 50 | echo "Play RocketMQ nameserver and broker image" 51 | echo "Starting RocketMQ nodes..." 52 | 53 | case "${BASE_IMAGE}" in 54 | alpine) 55 | start_namesrv_broker -alpine 56 | ;; 57 | centos) 58 | start_namesrv_broker 59 | ;; 60 | *) 61 | echo "${BASE_IMAGE} is not supported, supported base images: centos, alpine" 62 | exit 2 63 | ;; 64 | esac 65 | 66 | echo "Wait 10 seconds for service ready" 67 | 68 | sleep 10 69 | 70 | echo "Start producer..." 71 | # Produce messages 72 | docker exec -ti rmqbroker sh ./tools.sh org.apache.rocketmq.example.quickstart.Producer 73 | sleep 2 74 | echo "Start consumer..." 75 | # Consume messages 76 | docker exec -ti rmqbroker sh ./tools.sh org.apache.rocketmq.example.quickstart.Consumer 77 | -------------------------------------------------------------------------------- /install-operator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | make deploy 19 | 20 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package main 19 | 20 | import ( 21 | "flag" 22 | "os" 23 | 24 | rocketmqv1alpha1 "github.com/apache/rocketmq-operator/pkg/apis/rocketmq/v1alpha1" 25 | "github.com/apache/rocketmq-operator/pkg/controller/broker" 26 | "github.com/apache/rocketmq-operator/pkg/controller/console" 27 | rmqcontroller "github.com/apache/rocketmq-operator/pkg/controller/controller" 28 | "github.com/apache/rocketmq-operator/pkg/controller/nameservice" 29 | "github.com/apache/rocketmq-operator/pkg/controller/topictransfer" 30 | 31 | // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) 32 | // to ensure that exec-entrypoint and run can make use of them. 33 | _ "k8s.io/client-go/plugin/pkg/client/auth" 34 | 35 | "k8s.io/apimachinery/pkg/runtime" 36 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 37 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 38 | ctrl "sigs.k8s.io/controller-runtime" 39 | "sigs.k8s.io/controller-runtime/pkg/healthz" 40 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 41 | //+kubebuilder:scaffold:imports 42 | ) 43 | 44 | //+kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=get;list;watch;create;update;patch;delete 45 | //+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete 46 | //+kubebuilder:rbac:groups="",resources=events,verbs=create;patch 47 | 48 | var ( 49 | scheme = runtime.NewScheme() 50 | setupLog = ctrl.Log.WithName("setup") 51 | ) 52 | 53 | func init() { 54 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 55 | 56 | utilruntime.Must(rocketmqv1alpha1.AddToScheme(scheme)) 57 | //+kubebuilder:scaffold:scheme 58 | } 59 | 60 | func main() { 61 | var metricsAddr string 62 | var enableLeaderElection bool 63 | var probeAddr string 64 | var watchNamespace string 65 | flag.StringVar(&watchNamespace, "watch-namespace", os.Getenv("WATCH_NAMESPACE"), "The namespace to watch, if not specified, all namespaces will be watched") 66 | flag.StringVar(&metricsAddr, "metrics-bind-address", ":8383", "The address the metric endpoint binds to.") 67 | flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") 68 | flag.BoolVar(&enableLeaderElection, "leader-elect", false, 69 | "Enable leader election for controller manager. "+ 70 | "Enabling this will ensure there is only one active controller manager.") 71 | opts := zap.Options{ 72 | Development: true, 73 | } 74 | opts.BindFlags(flag.CommandLine) 75 | flag.Parse() 76 | 77 | ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) 78 | 79 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 80 | Scheme: scheme, 81 | MetricsBindAddress: metricsAddr, 82 | Port: 9443, 83 | HealthProbeBindAddress: probeAddr, 84 | LeaderElection: enableLeaderElection, 85 | LeaderElectionID: "2516c052.apache.org", 86 | Namespace: watchNamespace, 87 | }) 88 | if err != nil { 89 | setupLog.Error(err, "unable to start manager") 90 | os.Exit(1) 91 | } 92 | 93 | // Setup all Controllers 94 | if err := broker.SetupWithManager(mgr); err != nil { 95 | setupLog.Error(err, "unable to add broker controller to manager") 96 | os.Exit(1) 97 | } 98 | 99 | if err := console.SetupWithManager(mgr); err != nil { 100 | setupLog.Error(err, "unable to add console controller to manager") 101 | os.Exit(1) 102 | } 103 | 104 | if err := nameservice.SetupWithManager(mgr); err != nil { 105 | setupLog.Error(err, "unable to add nameservice controller to manager") 106 | os.Exit(1) 107 | } 108 | 109 | if err := topictransfer.SetupWithManager(mgr); err != nil { 110 | setupLog.Error(err, "unable to add topictransfer controller to manager") 111 | os.Exit(1) 112 | } 113 | 114 | if err := rmqcontroller.SetupWithManager(mgr); err != nil { 115 | setupLog.Error(err, "unable to add dledger controller to manager") 116 | os.Exit(1) 117 | } 118 | 119 | //+kubebuilder:scaffold:builder 120 | 121 | if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { 122 | setupLog.Error(err, "unable to set up health check") 123 | os.Exit(1) 124 | } 125 | if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { 126 | setupLog.Error(err, "unable to set up ready check") 127 | os.Exit(1) 128 | } 129 | 130 | setupLog.Info("starting manager") 131 | if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 132 | setupLog.Error(err, "problem running manager") 133 | os.Exit(1) 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/group.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // Package rocketmq contains rocketmq API versions. 19 | // 20 | // This file ensures Go source parsers acknowledge the rocketmq package 21 | // and any child packages. It can be removed if any other Go source files are 22 | // added to this package. 23 | package rocketmq 24 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/broker_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | corev1 "k8s.io/api/core/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 26 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 27 | 28 | // BrokerSpec defines the desired state of Broker 29 | // +k8s:openapi-gen=true 30 | type BrokerSpec struct { 31 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 32 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 33 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 34 | // Size of broker clusters 35 | Size int `json:"size"` 36 | // NameServers defines the name service list e.g. 192.168.1.1:9876;192.168.1.2:9876 37 | NameServers string `json:"nameServers,omitempty"` 38 | // ClusterMode defines the way to be a broker cluster, valid values can be one of the following: 39 | // - STATIC: default clusters with static broker roles 40 | // - CONTROLLER: clusters with DLedger Controller since RocketMQ 5.0 41 | // - CONTAINER: [NOT implemented yet] enabling broker containers since RocketMQ 5.0 42 | ClusterMode string `json:"clusterMode,omitempty"` 43 | // ReplicaPerGroup each broker cluster's replica number 44 | ReplicaPerGroup int `json:"replicaPerGroup"` 45 | // BaseImage is the broker image to use for the Pods 46 | BrokerImage string `json:"brokerImage"` 47 | // ImagePullPolicy defines how the image is pulled 48 | ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy"` 49 | // HostNetwork can be true or false 50 | HostNetwork bool `json:"hostNetwork,omitempty"` 51 | // AllowRestart defines whether allow pod restart 52 | AllowRestart bool `json:"allowRestart"` 53 | // Resources describes the compute resource requirements 54 | Resources corev1.ResourceRequirements `json:"resources"` 55 | // StorageMode can be EmptyDir, HostPath, StorageClass 56 | StorageMode string `json:"storageMode"` 57 | // HostPath is the local path to store data 58 | HostPath string `json:"hostPath"` 59 | // Env defines custom env, e.g. BROKER_MEM 60 | Env []corev1.EnvVar `json:"env"` 61 | // Volumes define the broker.conf 62 | Volumes []corev1.Volume `json:"volumes"` 63 | // VolumeClaimTemplates defines the StorageClass 64 | VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates"` 65 | // The name of pod where the metadata from 66 | ScalePodName string `json:"scalePodName"` 67 | // Pod Security Context 68 | PodSecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` 69 | // Pod Annotations 70 | PodAnnotations map[string]string `json:"podAnnotations,omitempty"` 71 | // Container Security Context 72 | ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` 73 | // The secrets used to pull image from private registry 74 | ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` 75 | // Affinity the pod's scheduling constraints 76 | Affinity *corev1.Affinity `json:"affinity,omitempty"` 77 | // Tolerations the pod's tolerations. 78 | Tolerations []corev1.Toleration `json:"tolerations,omitempty"` 79 | // NodeSelector is a selector which must be true for the pod to fit on a node 80 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 81 | // PriorityClassName indicates the pod's priority 82 | PriorityClassName string `json:"priorityClassName,omitempty"` 83 | // ServiceAccountName 84 | ServiceAccountName string `json:"serviceAccountName,omitempty"` 85 | } 86 | 87 | // BrokerStatus defines the observed state of Broker 88 | // +k8s:openapi-gen=true 89 | type BrokerStatus struct { 90 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 91 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 92 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 93 | Nodes []string `json:"nodes"` 94 | Size int `json:"size"` 95 | } 96 | 97 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 98 | 99 | // Broker is the Schema for the brokers API 100 | // +k8s:openapi-gen=true 101 | // +kubebuilder:printcolumn:name="Size",type="integer",JSONPath=".spec.size" 102 | // +kubebuilder:printcolumn:name="Replica-Per-Group",type="integer",JSONPath=".spec.replicaPerGroup" 103 | // +kubebuilder:printcolumn:name="Allow-Restart",type="boolean",JSONPath=".spec.allowRestart" 104 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 105 | // +kubebuilder:subresource:status 106 | type Broker struct { 107 | metav1.TypeMeta `json:",inline"` 108 | metav1.ObjectMeta `json:"metadata,omitempty"` 109 | 110 | Spec BrokerSpec `json:"spec,omitempty"` 111 | Status BrokerStatus `json:"status,omitempty"` 112 | } 113 | 114 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 115 | 116 | // BrokerList contains a list of Broker 117 | type BrokerList struct { 118 | metav1.TypeMeta `json:",inline"` 119 | metav1.ListMeta `json:"metadata,omitempty"` 120 | Items []Broker `json:"items"` 121 | } 122 | 123 | func init() { 124 | SchemeBuilder.Register(&Broker{}, &BrokerList{}) 125 | } 126 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/console_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | v1 "k8s.io/api/apps/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 26 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 27 | 28 | // ConsoleSpec defines the desired state of Console 29 | // +k8s:openapi-gen=true 30 | type ConsoleSpec struct { 31 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 32 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 33 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 34 | ConsoleDeployment v1.Deployment `json:"consoleDeployment"` 35 | // NameServers defines the name service list e.g. 192.168.1.1:9876;192.168.1.2:9876 36 | NameServers string `json:"nameServers,omitempty"` 37 | } 38 | 39 | // ConsoleStatus defines the observed state of Console 40 | // +k8s:openapi-gen=true 41 | type ConsoleStatus struct { 42 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 43 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 44 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 45 | } 46 | 47 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 48 | 49 | // Console is the Schema for the consoles API 50 | // +k8s:openapi-gen=true 51 | // +kubebuilder:subresource:status 52 | // +kubebuilder:printcolumn:name="Size",type="integer",JSONPath=".spec.consoleDeployment.spec.replicas" 53 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 54 | // +kubebuilder:resource:path=consoles,scope=Namespaced 55 | type Console struct { 56 | metav1.TypeMeta `json:",inline"` 57 | metav1.ObjectMeta `json:"metadata,omitempty"` 58 | 59 | Spec ConsoleSpec `json:"spec,omitempty"` 60 | Status ConsoleStatus `json:"status,omitempty"` 61 | } 62 | 63 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 64 | 65 | // ConsoleList contains a list of Console 66 | type ConsoleList struct { 67 | metav1.TypeMeta `json:",inline"` 68 | metav1.ListMeta `json:"metadata,omitempty"` 69 | Items []Console `json:"items"` 70 | } 71 | 72 | func init() { 73 | SchemeBuilder.Register(&Console{}, &ConsoleList{}) 74 | } 75 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/controller_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | corev1 "k8s.io/api/core/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 26 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 27 | 28 | // ControllerSpec defines the desired state of Controller 29 | // +k8s:openapi-gen=true 30 | type ControllerSpec struct { 31 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 32 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 33 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 34 | 35 | // size of controller 36 | Size int `json:"size"` 37 | 38 | // BaseImage is the controller image to use for the Pods 39 | ControllerImage string `json:"controllerImage"` 40 | // ImagePullPolicy defines how the image is pulled 41 | ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` 42 | 43 | // Resources describes the compute resource requirements 44 | Resources corev1.ResourceRequirements `json:"resources"` 45 | // StorageMode can be EmptyDir, HostPath, StorageClass 46 | StorageMode string `json:"storageMode"` 47 | // HostPath is the local path to store data 48 | HostPath string `json:"hostPath"` 49 | // Env defines custom env 50 | Env []corev1.EnvVar `json:"env,omitempty"` 51 | 52 | // VolumeClaimTemplates defines the StorageClass 53 | VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates"` 54 | 55 | // Pod Security Context 56 | PodSecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` 57 | // Pod Annotations 58 | PodAnnotations map[string]string `json:"podAnnotations,omitempty"` 59 | // Container Security Context 60 | ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` 61 | // The secrets used to pull image from private registry 62 | ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` 63 | // Affinity the pod's scheduling constraints 64 | Affinity *corev1.Affinity `json:"affinity,omitempty"` 65 | // Tolerations the pod's tolerations. 66 | Tolerations []corev1.Toleration `json:"tolerations,omitempty"` 67 | // NodeSelector is a selector which must be true for the pod to fit on a node 68 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 69 | // PriorityClassName indicates the pod's priority 70 | PriorityClassName string `json:"priorityClassName,omitempty"` 71 | // ServiceAccountName 72 | ServiceAccountName string `json:"serviceAccountName,omitempty"` 73 | } 74 | 75 | // ControllerStatus defines the observed state of Controller 76 | // +k8s:openapi-gen=true 77 | type ControllerStatus struct { 78 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 79 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 80 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 81 | Nodes []string `json:"nodes"` 82 | Size int `json:"size"` 83 | } 84 | 85 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 86 | 87 | // Controller is the Schema for the Controllers API 88 | // +k8s:openapi-gen=true 89 | // +kubebuilder:printcolumn:name="Size",type="integer",JSONPath=".spec.size" 90 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 91 | // +kubebuilder:subresource:status 92 | type Controller struct { 93 | metav1.TypeMeta `json:",inline"` 94 | metav1.ObjectMeta `json:"metadata,omitempty"` 95 | 96 | Spec ControllerSpec `json:"spec,omitempty"` 97 | Status ControllerStatus `json:"status,omitempty"` 98 | } 99 | 100 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 101 | 102 | // ControllerList contains a list of Controller 103 | type ControllerList struct { 104 | metav1.TypeMeta `json:",inline"` 105 | metav1.ListMeta `json:"metadata,omitempty"` 106 | Items []Controller `json:"items"` 107 | } 108 | 109 | func init() { 110 | SchemeBuilder.Register(&Controller{}, &ControllerList{}) 111 | } 112 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // NOTE: Boilerplate only. Ignore this file. 19 | 20 | // Package v1alpha1 contains API Schema definitions for the rocketmq v1alpha1 API group 21 | // +k8s:deepcopy-gen=package,register 22 | // +groupName=rocketmq.apache.org 23 | package v1alpha1 24 | 25 | import ( 26 | "k8s.io/apimachinery/pkg/runtime/schema" 27 | "sigs.k8s.io/controller-runtime/pkg/scheme" 28 | ) 29 | 30 | var ( 31 | // GroupVersion is group version used to register these objects 32 | GroupVersion = schema.GroupVersion{Group: "rocketmq.apache.org", Version: "v1alpha1"} 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 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/nameservice_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | corev1 "k8s.io/api/core/v1" 22 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 | ) 24 | 25 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 26 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 27 | 28 | // NameServiceSpec defines the desired state of NameService 29 | // +k8s:openapi-gen=true 30 | type NameServiceSpec struct { 31 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 32 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 33 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 34 | // Size is the number of the name service Pod 35 | Size int32 `json:"size"` 36 | //NameServiceImage is the name service image 37 | NameServiceImage string `json:"nameServiceImage"` 38 | // ImagePullPolicy defines how the image is pulled. 39 | ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy"` 40 | // HostNetwork can be true or false 41 | HostNetwork bool `json:"hostNetwork"` 42 | // dnsPolicy defines how a pod's DNS will be configured 43 | DNSPolicy corev1.DNSPolicy `json:"dnsPolicy"` 44 | // Resources describes the compute resource requirements 45 | Resources corev1.ResourceRequirements `json:"resources"` 46 | // StorageMode can be EmptyDir, HostPath, StorageClass 47 | StorageMode string `json:"storageMode"` 48 | // HostPath is the local path to store data 49 | HostPath string `json:"hostPath"` 50 | // Env defines custom env, e.g. JAVA_OPT_EXT 51 | Env []corev1.EnvVar `json:"env,omitempty"` 52 | // VolumeClaimTemplates defines the StorageClass 53 | VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates"` 54 | // Pod Security Context 55 | PodSecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"` 56 | // Pod Annotations 57 | PodAnnotations map[string]string `json:"podAnnotations,omitempty"` 58 | // Container Security Context 59 | ContainerSecurityContext *corev1.SecurityContext `json:"containerSecurityContext,omitempty"` 60 | // The secrets used to pull image from private registry 61 | ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` 62 | // Affinity the pod's scheduling constraints 63 | Affinity *corev1.Affinity `json:"affinity,omitempty"` 64 | // Tolerations the pod's tolerations. 65 | Tolerations []corev1.Toleration `json:"tolerations,omitempty"` 66 | // NodeSelector is a selector which must be true for the pod to fit on a node 67 | NodeSelector map[string]string `json:"nodeSelector,omitempty"` 68 | // PriorityClassName indicates the pod's priority 69 | PriorityClassName string `json:"priorityClassName,omitempty"` 70 | // ServiceAccountName 71 | ServiceAccountName string `json:"serviceAccountName,omitempty"` 72 | } 73 | 74 | // NameServiceStatus defines the observed state of NameService 75 | // +k8s:openapi-gen=true 76 | type NameServiceStatus struct { 77 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 78 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 79 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 80 | // NameServers is the name service ip list 81 | NameServers []string `json:"nameServers"` 82 | } 83 | 84 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 85 | 86 | // NameService is the Schema for the nameservices API 87 | // +k8s:openapi-gen=true 88 | // +kubebuilder:printcolumn:name="Size",type="integer",JSONPath=".spec.size" 89 | // +kubebuilder:printcolumn:name="Host-Network",type="boolean",JSONPath=".spec.hostNetwork" 90 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 91 | // +kubebuilder:subresource:status 92 | type NameService struct { 93 | metav1.TypeMeta `json:",inline"` 94 | metav1.ObjectMeta `json:"metadata,omitempty"` 95 | 96 | Spec NameServiceSpec `json:"spec,omitempty"` 97 | Status NameServiceStatus `json:"status,omitempty"` 98 | } 99 | 100 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 101 | 102 | // NameServiceList contains a list of NameService 103 | type NameServiceList struct { 104 | metav1.TypeMeta `json:",inline"` 105 | metav1.ListMeta `json:"metadata,omitempty"` 106 | Items []NameService `json:"items"` 107 | } 108 | 109 | func init() { 110 | SchemeBuilder.Register(&NameService{}, &NameServiceList{}) 111 | } 112 | -------------------------------------------------------------------------------- /pkg/apis/rocketmq/v1alpha1/topictransfer_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package v1alpha1 19 | 20 | import ( 21 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 22 | ) 23 | 24 | // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! 25 | // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. 26 | 27 | // TopicTransferSpec defines the desired state of TopicTransfer 28 | // +k8s:openapi-gen=true 29 | type TopicTransferSpec struct { 30 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 31 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 32 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 33 | 34 | // Topic name 35 | Topic string `json:"topic,omitempty"` 36 | // The cluster where the transferred topic from 37 | SourceCluster string `json:"sourceCluster,omitempty"` 38 | // The cluster where the topic will be transferred to 39 | TargetCluster string `json:"targetCluster,omitempty"` 40 | } 41 | 42 | // TopicTransferStatus defines the observed state of TopicTransfer 43 | // +k8s:openapi-gen=true 44 | type TopicTransferStatus struct { 45 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 46 | // Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file 47 | // Add custom validation using kubebuilder tags: https://book-v1.book.kubebuilder.io/beyond_basics/generating_crd.html 48 | } 49 | 50 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 51 | 52 | // TopicTransfer is the Schema for the topictransfers API 53 | // +k8s:openapi-gen=true 54 | // +kubebuilder:subresource:status 55 | type TopicTransfer struct { 56 | metav1.TypeMeta `json:",inline"` 57 | metav1.ObjectMeta `json:"metadata,omitempty"` 58 | 59 | Spec TopicTransferSpec `json:"spec,omitempty"` 60 | Status TopicTransferStatus `json:"status,omitempty"` 61 | } 62 | 63 | // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object 64 | 65 | // TopicTransferList contains a list of TopicTransfer 66 | type TopicTransferList struct { 67 | metav1.TypeMeta `json:",inline"` 68 | metav1.ListMeta `json:"metadata,omitempty"` 69 | Items []TopicTransfer `json:"items"` 70 | } 71 | 72 | func init() { 73 | SchemeBuilder.Register(&TopicTransfer{}, &TopicTransferList{}) 74 | } 75 | -------------------------------------------------------------------------------- /pkg/constants/constants.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // Package constants defines some global constants 19 | package constants 20 | 21 | import "os" 22 | 23 | var ( 24 | rocketmqHome = os.Getenv("ROCKETMQ_HOME") 25 | 26 | // AdminToolDir is the RocketMQ Admin directory in operator image 27 | AdminToolDir = rocketmqHome + "/bin/mqadmin" 28 | ) 29 | 30 | const ( 31 | // TODO: get paths by container ENV or actual value instead of fixed constant 32 | DataPath = "/root" 33 | 34 | // BrokerContainerName is the name of broker container 35 | BrokerContainerName = "broker" 36 | 37 | // BasicCommand is basic command of exec function 38 | BasicCommand = "sh" 39 | 40 | // StoreConfigDir is the directory of config file 41 | StoreConfigDir = DataPath + "/store/config" 42 | 43 | // TopicJsonDir is the directory of topics.json 44 | TopicJsonDir = StoreConfigDir + "/topics.json" 45 | 46 | // SubscriptionGroupJsonDir is the directory of subscriptionGroup.json 47 | SubscriptionGroupJsonDir = StoreConfigDir + "/subscriptionGroup.json" 48 | 49 | // BrokerConfigDir is the directory of the mounted config file 50 | BrokerConfigPath = DataPath + "/rocketmq/broker/conf" 51 | 52 | // BrokerConfigName is the name of mounted configuration file 53 | BrokerConfigName = "broker-common.conf" 54 | 55 | // UpdateBrokerConfig is update broker config command 56 | UpdateBrokerConfig = "updateBrokerConfig" 57 | 58 | // ParamNameServiceAddress is the name of name server list parameter 59 | ParamNameServiceAddress = "namesrvAddr" 60 | 61 | // EnvNameServiceAddress is the container environment variable name of name server list 62 | EnvNameServiceAddress = "NAMESRV_ADDR" 63 | 64 | // EnvBrokerId is the container environment variable name of broker id 65 | EnvBrokerId = "BROKER_ID" 66 | 67 | // EnvBrokerClusterName is the container environment variable name of broker cluster name 68 | EnvBrokerClusterName = "BROKER_CLUSTER_NAME" 69 | 70 | // EnvBrokerName is the container environment variable name of broker name 71 | EnvBrokerName = "BROKER_NAME" 72 | 73 | // LogMountPath is the directory of RocketMQ log files 74 | LogMountPath = DataPath + "/logs" 75 | 76 | // StoreMountPath is the directory of RocketMQ store files 77 | StoreMountPath = DataPath + "/store" 78 | 79 | // LogSubPathName is the sub-path name of log dir under mounted host dir 80 | LogSubPathName = "logs" 81 | 82 | // StoreSubPathName is the sub-path name of store dir under mounted host dir 83 | StoreSubPathName = "store" 84 | 85 | // NameServiceMainContainerPort is the main port number of name server container 86 | NameServiceMainContainerPort = 9876 87 | 88 | // NameServiceMainContainerPortName is the main port name of name server container 89 | NameServiceMainContainerPortName = "main" 90 | 91 | // BrokerVipContainerPort is the VIP port number of broker container 92 | BrokerVipContainerPort = 10909 93 | 94 | // BrokerVipContainerPortName is the VIP port name of broker container 95 | BrokerVipContainerPortName = "vip" 96 | 97 | // BrokerMainContainerPort is the main port number of broker container 98 | BrokerMainContainerPort = 10911 99 | 100 | // BrokerMainContainerPortName is the main port name of broker container 101 | BrokerMainContainerPortName = "main" 102 | 103 | // BrokerHighAvailabilityContainerPort is the high availability port number of broker container 104 | BrokerHighAvailabilityContainerPort = 10912 105 | 106 | // BrokerHighAvailabilityContainerPortName is the high availability port name of broker container 107 | BrokerHighAvailabilityContainerPortName = "ha" 108 | 109 | // ConsoleContainerPort is the port number of RocketMQ Console container 110 | ConsoleContainerPort = 8080 111 | 112 | // ConsoleContainerPortName is the port name of RocketMQ Console container 113 | ConsoleContainerPortName = "console" 114 | 115 | // StorageModeStorageClass is the name of StorageClass storage mode 116 | StorageModeStorageClass = "StorageClass" 117 | 118 | // StorageModeEmptyDir is the name of EmptyDir storage mode 119 | StorageModeEmptyDir = "EmptyDir" 120 | 121 | // StorageModeHostPath is the name pf HostPath storage mode 122 | StorageModeHostPath = "HostPath" 123 | 124 | // RestartBrokerPodIntervalInSecond is restart broker pod interval in second 125 | RestartBrokerPodIntervalInSecond = 30 126 | 127 | // WaitForNameServerReadyInSecond is the time broker sleep for waiting nameserver ready in second 128 | WaitForNameServerReadyInSecond = 1 129 | 130 | // MinMetadataJsonFileSize is the threshold value if file length is lower than this will be considered as invalid 131 | MinMetadataJsonFileSize = 5 132 | 133 | // MinIpListLength is the threshold value if the name server list parameter length is shorter than this will be considered as invalid 134 | MinIpListLength = 8 135 | 136 | // CheckConsumeFinishIntervalInSecond is the interval of checking whether the consumption process is finished in second 137 | CheckConsumeFinishIntervalInSecond = 5 138 | 139 | // RequeueIntervalInSecond is an universal interval of the reconcile function 140 | RequeueIntervalInSecond = 6 141 | 142 | // Topic is the topic field index of the output when using command check consume progress 143 | Topic = 0 144 | 145 | // BrokerName is the broker name field index of the output when using command check consume progress 146 | BrokerName = 1 147 | 148 | // Diff is the diff field index of the output when using command check consume progress 149 | Diff = 6 150 | 151 | // TopicListTopic is the topic field index of the output when using command check topic list 152 | TopicListTopic = 1 153 | 154 | // TopicListConsumerGroup is the consumer group field index of the output when using command check topic list 155 | TopicListConsumerGroup = 2 156 | 157 | // ControllerContainerName is the name of Controller container 158 | ControllerContainerName = "controller" 159 | 160 | // EnvControllerDLegerPeers is the container environment variable name of DLeger peers 161 | // Format: {unique id}-{IP of that controller} 162 | EnvControllerDLegerPeers = "controllerDLegerPeers" 163 | 164 | // the container environment variable name of persistent storage directory 165 | EnvControllerStorePath = "controllerStorePath" 166 | 167 | // the container environment variable name of DLeger group 168 | EnvControllerDLegerGroup = "controllerDLegerGroup" 169 | 170 | // the container environment variable name of in Broker 171 | EnvEnableControllerMode = "enableControllerMode" 172 | 173 | // EnvControllerAddr is the container environment variable name of Controller address in Broker 174 | EnvControllerAddr = "controllerAddr" 175 | 176 | // EnvPodIp is the container environment variable name of pod ip. 177 | EnvPodIp = "POD_IP" 178 | ) 179 | -------------------------------------------------------------------------------- /pkg/controller/console/console_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package console 19 | 20 | import ( 21 | "context" 22 | "fmt" 23 | "reflect" 24 | "time" 25 | 26 | rocketmqv1alpha1 "github.com/apache/rocketmq-operator/pkg/apis/rocketmq/v1alpha1" 27 | cons "github.com/apache/rocketmq-operator/pkg/constants" 28 | "github.com/apache/rocketmq-operator/pkg/share" 29 | appsv1 "k8s.io/api/apps/v1" 30 | corev1 "k8s.io/api/core/v1" 31 | "k8s.io/apimachinery/pkg/api/errors" 32 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 33 | "k8s.io/apimachinery/pkg/runtime" 34 | "k8s.io/apimachinery/pkg/types" 35 | "sigs.k8s.io/controller-runtime/pkg/client" 36 | "sigs.k8s.io/controller-runtime/pkg/controller" 37 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 38 | "sigs.k8s.io/controller-runtime/pkg/handler" 39 | logf "sigs.k8s.io/controller-runtime/pkg/log" 40 | "sigs.k8s.io/controller-runtime/pkg/manager" 41 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 42 | "sigs.k8s.io/controller-runtime/pkg/source" 43 | ) 44 | 45 | var log = logf.Log.WithName("controller_console") 46 | 47 | /** 48 | * USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller 49 | * business logic. Delete these comments after modifying this file.* 50 | */ 51 | 52 | // SetupWithManager creates a new Console Controller and adds it to the Manager. The Manager will set fields on the Controller 53 | // and Start it when the Manager is Started. 54 | func SetupWithManager(mgr manager.Manager) error { 55 | return add(mgr, newReconciler(mgr)) 56 | } 57 | 58 | // newReconciler returns a new reconcile.Reconciler 59 | func newReconciler(mgr manager.Manager) reconcile.Reconciler { 60 | return &ReconcileConsole{client: mgr.GetClient(), scheme: mgr.GetScheme()} 61 | } 62 | 63 | // add adds a new Controller to mgr with r as the reconcile.Reconciler 64 | func add(mgr manager.Manager, r reconcile.Reconciler) error { 65 | // Create a new controller 66 | c, err := controller.New("console-controller", mgr, controller.Options{Reconciler: r}) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | // Watch for changes to primary resource Console 72 | err = c.Watch(&source.Kind{Type: &rocketmqv1alpha1.Console{}}, &handler.EnqueueRequestForObject{}) 73 | if err != nil { 74 | return err 75 | } 76 | 77 | // TODO(user): Modify this to be the types you create that are owned by the primary resource 78 | // Watch for changes to secondary resource Pods and requeue the owner Console 79 | err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{ 80 | IsController: true, 81 | OwnerType: &rocketmqv1alpha1.Console{}, 82 | }) 83 | if err != nil { 84 | return err 85 | } 86 | 87 | return nil 88 | } 89 | 90 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=consoles,verbs=get;list;watch;create;update;patch;delete 91 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=consoles/status,verbs=get;update;patch 92 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=consoles/finalizers,verbs=update 93 | //+kubebuilder:rbac:groups="apps",resources=deployments,verbs=get;list;watch;create;update;patch;delete 94 | 95 | // ReconcileConsole reconciles a Console object 96 | type ReconcileConsole struct { 97 | // This client, initialized using mgr.Client() above, is a split client 98 | // that reads objects from the cache and writes to the apiserver 99 | client client.Client 100 | scheme *runtime.Scheme 101 | } 102 | 103 | // Reconcile reads that state of the cluster for a Console object and makes changes based on the state read 104 | // and what is in the Console.Spec 105 | // TODO(user): Modify this Reconcile function to implement your Controller logic. This example creates 106 | // a Pod as an example 107 | // Note: 108 | // The Controller will requeue the Request to be processed again if the returned error is non-nil or 109 | // Result.Requeue is true, otherwise upon completion it will remove the work from the queue. 110 | func (r *ReconcileConsole) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { 111 | reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) 112 | reqLogger.Info("Reconciling Console") 113 | 114 | // Fetch the Console instance 115 | instance := &rocketmqv1alpha1.Console{} 116 | err := r.client.Get(context.TODO(), request.NamespacedName, instance) 117 | if err != nil { 118 | if errors.IsNotFound(err) { 119 | // Request object not found, could have been deleted after reconcile request. 120 | // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 121 | // Return and don't requeue 122 | return reconcile.Result{}, nil 123 | } 124 | // Error reading the object - requeue the request. 125 | return reconcile.Result{}, err 126 | } 127 | 128 | if instance.Spec.NameServers == "" { 129 | // wait for name server ready if nameServers is omitted 130 | for { 131 | if share.IsNameServersStrInitialized { 132 | break 133 | } else { 134 | log.Info("Waiting for name server ready...") 135 | time.Sleep(time.Duration(cons.WaitForNameServerReadyInSecond) * time.Second) 136 | } 137 | } 138 | } else { 139 | share.NameServersStr = instance.Spec.NameServers 140 | } 141 | 142 | consoleDeployment := newDeploymentForCR(instance) 143 | 144 | // Set Console instance as the owner and controller 145 | if err := controllerutil.SetControllerReference(instance, consoleDeployment, r.scheme); err != nil { 146 | return reconcile.Result{}, err 147 | } 148 | 149 | // Check if this Pod already exists 150 | found := &appsv1.Deployment{} 151 | err = r.client.Get(context.TODO(), types.NamespacedName{Name: consoleDeployment.Name, Namespace: consoleDeployment.Namespace}, found) 152 | if err != nil && errors.IsNotFound(err) { 153 | reqLogger.Info("Creating RocketMQ Console Deployment", "Namespace", consoleDeployment, "Name", consoleDeployment.Name) 154 | err = r.client.Create(context.TODO(), consoleDeployment) 155 | if err != nil { 156 | return reconcile.Result{}, err 157 | } 158 | 159 | // created successfully - don't requeue 160 | return reconcile.Result{}, nil 161 | } else if err != nil { 162 | return reconcile.Result{}, err 163 | } 164 | 165 | // Support console deployment update 166 | if !reflect.DeepEqual(instance.Spec.ConsoleDeployment.Spec.Replicas, found.Spec.Replicas) || 167 | !reflect.DeepEqual(instance.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Resources, found.Spec.Template.Spec.Containers[0].Resources) { 168 | 169 | found.Spec.Replicas = instance.Spec.ConsoleDeployment.Spec.Replicas 170 | found.Spec.Template.Spec.Containers[0].Resources = instance.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Resources 171 | err = r.client.Update(context.TODO(), found) 172 | if err != nil { 173 | reqLogger.Error(err, "Failed to update console CR", "Namespace", found.Namespace, "Name", found.Name) 174 | } else { 175 | reqLogger.Info("Successfully updated console CR", "Namespace", found.Namespace, "Name", found.Name) 176 | } 177 | } 178 | 179 | // TODO: update console if name server address changes 180 | 181 | // CR already exists - don't requeue 182 | reqLogger.Info("Skip reconcile: RocketMQ Console Deployment already exists", "Namespace", found.Namespace, "Name", found.Name) 183 | return reconcile.Result{}, nil 184 | } 185 | 186 | // newDeploymentForCR returns a deployment pod with modifying the ENV 187 | func newDeploymentForCR(cr *rocketmqv1alpha1.Console) *appsv1.Deployment { 188 | env := corev1.EnvVar{ 189 | Name: "JAVA_OPTS", 190 | Value: fmt.Sprintf("-Drocketmq.namesrv.addr=%s -Dcom.rocketmq.sendMessageWithVIPChannel=false", share.NameServersStr), 191 | } 192 | 193 | dep := &appsv1.Deployment{ 194 | ObjectMeta: metav1.ObjectMeta{ 195 | Name: cr.Name, 196 | Namespace: cr.Namespace, 197 | }, 198 | Spec: appsv1.DeploymentSpec{ 199 | Replicas: cr.Spec.ConsoleDeployment.Spec.Replicas, 200 | Selector: &metav1.LabelSelector{ 201 | MatchLabels: cr.Spec.ConsoleDeployment.Spec.Selector.MatchLabels, 202 | }, 203 | Template: corev1.PodTemplateSpec{ 204 | ObjectMeta: metav1.ObjectMeta{ 205 | Labels: cr.Spec.ConsoleDeployment.Spec.Template.ObjectMeta.Labels, 206 | Annotations: cr.Spec.ConsoleDeployment.Spec.Template.ObjectMeta.Annotations, 207 | }, 208 | Spec: corev1.PodSpec{ 209 | ServiceAccountName: cr.Spec.ConsoleDeployment.Spec.Template.Spec.ServiceAccountName, 210 | Affinity: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Affinity, 211 | ImagePullSecrets: cr.Spec.ConsoleDeployment.Spec.Template.Spec.ImagePullSecrets, 212 | Containers: []corev1.Container{{ 213 | Resources: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Resources, 214 | Image: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Image, 215 | Args: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Args, 216 | Name: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Name, 217 | ImagePullPolicy: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].ImagePullPolicy, 218 | Env: append(cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Env, env), 219 | Ports: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].Ports, 220 | VolumeMounts: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Containers[0].VolumeMounts, 221 | }}, 222 | Volumes: cr.Spec.ConsoleDeployment.Spec.Template.Spec.Volumes, 223 | }, 224 | }, 225 | }, 226 | } 227 | 228 | return dep 229 | } 230 | -------------------------------------------------------------------------------- /pkg/controller/nameservice/nameservice_controller.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // Package nameservice contains the implementation of the NameService CRD reconcile function 19 | package nameservice 20 | 21 | import ( 22 | "context" 23 | "os/exec" 24 | "reflect" 25 | "sort" 26 | "strconv" 27 | "strings" 28 | "time" 29 | 30 | "github.com/google/uuid" 31 | 32 | rocketmqv1alpha1 "github.com/apache/rocketmq-operator/pkg/apis/rocketmq/v1alpha1" 33 | cons "github.com/apache/rocketmq-operator/pkg/constants" 34 | "github.com/apache/rocketmq-operator/pkg/share" 35 | appsv1 "k8s.io/api/apps/v1" 36 | corev1 "k8s.io/api/core/v1" 37 | "k8s.io/apimachinery/pkg/api/errors" 38 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 39 | "k8s.io/apimachinery/pkg/labels" 40 | "k8s.io/apimachinery/pkg/runtime" 41 | "k8s.io/apimachinery/pkg/types" 42 | "sigs.k8s.io/controller-runtime/pkg/client" 43 | "sigs.k8s.io/controller-runtime/pkg/controller" 44 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 45 | "sigs.k8s.io/controller-runtime/pkg/handler" 46 | logf "sigs.k8s.io/controller-runtime/pkg/log" 47 | "sigs.k8s.io/controller-runtime/pkg/manager" 48 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 49 | "sigs.k8s.io/controller-runtime/pkg/source" 50 | ) 51 | 52 | var log = logf.Log.WithName("controller_nameservice") 53 | 54 | /** 55 | * USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller 56 | * business logic. Delete these comments after modifying this file.* 57 | */ 58 | 59 | // SetupWithManager creates a new NameService Controller and adds it to the Manager. The Manager will set fields on the Controller 60 | // and Start it when the Manager is Started. 61 | func SetupWithManager(mgr manager.Manager) error { 62 | return add(mgr, newReconciler(mgr)) 63 | } 64 | 65 | // newReconciler returns a new reconcile.Reconciler 66 | func newReconciler(mgr manager.Manager) reconcile.Reconciler { 67 | return &ReconcileNameService{client: mgr.GetClient(), scheme: mgr.GetScheme()} 68 | } 69 | 70 | // add adds a new Controller to mgr with r as the reconcile.Reconciler 71 | func add(mgr manager.Manager, r reconcile.Reconciler) error { 72 | // Create a new controller 73 | c, err := controller.New("nameservice-controller", mgr, controller.Options{Reconciler: r}) 74 | if err != nil { 75 | return err 76 | } 77 | 78 | // Watch for changes to primary resource NameService 79 | err = c.Watch(&source.Kind{Type: &rocketmqv1alpha1.NameService{}}, &handler.EnqueueRequestForObject{}) 80 | if err != nil { 81 | return err 82 | } 83 | 84 | // TODO(user): Modify this to be the types you create that are owned by the primary resource 85 | // Watch for changes to secondary resource Pods and requeue the owner NameService 86 | err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{ 87 | IsController: true, 88 | OwnerType: &rocketmqv1alpha1.NameService{}, 89 | }) 90 | if err != nil { 91 | return err 92 | } 93 | 94 | return nil 95 | } 96 | 97 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=nameservices,verbs=get;list;watch;create;update;patch;delete 98 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=nameservices/status,verbs=get;update;patch 99 | //+kubebuilder:rbac:groups=rocketmq.apache.org,resources=nameservices/finalizers,verbs=update 100 | //+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch;create;update;patch;delete 101 | //+kubebuilder:rbac:groups="apps",resources=statefulsets,verbs=get;list;watch;create;update;patch;delete 102 | 103 | // ReconcileNameService reconciles a NameService object 104 | type ReconcileNameService struct { 105 | // This client, initialized using mgr.Client() above, is a split client 106 | // that reads objects from the cache and writes to the apiserver 107 | client client.Client 108 | scheme *runtime.Scheme 109 | } 110 | 111 | // Reconcile reads that state of the cluster for a NameService object and makes changes based on the state read 112 | // and what is in the NameService.Spec 113 | // TODO(user): Modify this Reconcile function to implement your Controller logic. This example creates 114 | // a Pod as an example 115 | // Note: 116 | // The Controller will requeue the Request to be processed again if the returned error is non-nil or 117 | // Result.Requeue is true, otherwise upon completion it will remove the work from the queue. 118 | func (r *ReconcileNameService) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) { 119 | reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) 120 | reqLogger.Info("Reconciling NameService") 121 | 122 | // Fetch the NameService instance 123 | instance := &rocketmqv1alpha1.NameService{} 124 | err := r.client.Get(context.TODO(), request.NamespacedName, instance) 125 | if err != nil { 126 | if errors.IsNotFound(err) { 127 | // Request object not found, could have been deleted after reconcile request. 128 | // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. 129 | // Return and don't requeue 130 | return reconcile.Result{}, nil 131 | } 132 | // Error reading the object - requeue the request. 133 | return reconcile.Result{}, err 134 | } 135 | 136 | // Check if the statefulSet already exists, if not create a new one 137 | found := &appsv1.StatefulSet{} 138 | 139 | dep := r.statefulSetForNameService(instance) 140 | err = r.client.Get(context.TODO(), types.NamespacedName{Name: dep.Name, Namespace: dep.Namespace}, found) 141 | if err != nil && errors.IsNotFound(err) { 142 | err = r.client.Create(context.TODO(), dep) 143 | if err != nil { 144 | reqLogger.Error(err, "Failed to create new StatefulSet of NameService", "StatefulSet.Namespace", dep.Namespace, "StatefulSet.Name", dep.Name) 145 | } 146 | // StatefulSet created successfully - return and requeue 147 | return reconcile.Result{Requeue: true}, nil 148 | } else if err != nil { 149 | reqLogger.Error(err, "Failed to get NameService StatefulSet.") 150 | } 151 | 152 | // Ensure the statefulSet size is the same as the spec 153 | size := instance.Spec.Size 154 | if *found.Spec.Replicas != size { 155 | found.Spec.Replicas = &size 156 | err = r.client.Update(context.TODO(), found) 157 | reqLogger.Info("NameService Updated") 158 | if err != nil { 159 | reqLogger.Error(err, "Failed to update StatefulSet.", "StatefulSet.Namespace", found.Namespace, "StatefulSet.Name", found.Name) 160 | return reconcile.Result{}, err 161 | } 162 | } 163 | 164 | return r.updateNameServiceStatus(instance, request, true) 165 | } 166 | 167 | func (r *ReconcileNameService) updateNameServiceStatus(instance *rocketmqv1alpha1.NameService, request reconcile.Request, requeue bool) (reconcile.Result, error) { 168 | reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) 169 | reqLogger.Info("Check the NameServers status") 170 | // List the pods for this nameService's statefulSet 171 | podList := &corev1.PodList{} 172 | labelSelector := labels.SelectorFromSet(labelsForNameService(instance.Name)) 173 | listOps := &client.ListOptions{ 174 | Namespace: instance.Namespace, 175 | LabelSelector: labelSelector, 176 | } 177 | err := r.client.List(context.TODO(), podList, listOps) 178 | if err != nil { 179 | reqLogger.Error(err, "Failed to list pods.", "NameService.Namespace", instance.Namespace, "NameService.Name", instance.Name) 180 | return reconcile.Result{Requeue: true}, err 181 | } 182 | hostIps := getNameServers(podList.Items) 183 | 184 | sort.Strings(hostIps) 185 | sort.Strings(instance.Status.NameServers) 186 | 187 | nameServerListStr := "" 188 | for _, value := range hostIps { 189 | nameServerListStr = nameServerListStr + value + ":9876;" 190 | } 191 | 192 | // Update status.NameServers if needed 193 | if !reflect.DeepEqual(hostIps, instance.Status.NameServers) { 194 | oldNameServerListStr := "" 195 | for _, value := range instance.Status.NameServers { 196 | oldNameServerListStr = oldNameServerListStr + value + ":9876;" 197 | } 198 | 199 | share.NameServersStr = nameServerListStr[:len(nameServerListStr)-1] 200 | reqLogger.Info("share.NameServersStr:" + share.NameServersStr) 201 | 202 | if len(oldNameServerListStr) <= cons.MinIpListLength { 203 | oldNameServerListStr = share.NameServersStr 204 | } else if len(share.NameServersStr) > cons.MinIpListLength { 205 | oldNameServerListStr = oldNameServerListStr[:len(oldNameServerListStr)-1] 206 | share.IsNameServersStrUpdated = true 207 | } 208 | reqLogger.Info("oldNameServerListStr:" + oldNameServerListStr) 209 | 210 | instance.Status.NameServers = hostIps 211 | err := r.client.Status().Update(context.TODO(), instance) 212 | // Update the NameServers status with the host ips 213 | reqLogger.Info("Updated the NameServers status with the host IP") 214 | if err != nil { 215 | reqLogger.Error(err, "Failed to update NameServers status of NameService.") 216 | return reconcile.Result{Requeue: true}, err 217 | } 218 | 219 | // use admin tool to update broker config 220 | if share.IsNameServersStrUpdated && (len(oldNameServerListStr) > cons.MinIpListLength) && (len(share.NameServersStr) > cons.MinIpListLength) { 221 | mqAdmin := cons.AdminToolDir 222 | subCmd := cons.UpdateBrokerConfig 223 | key := cons.ParamNameServiceAddress 224 | 225 | reqLogger.Info("share.GroupNum=broker.Spec.Size=" + strconv.Itoa(share.GroupNum)) 226 | 227 | clusterName := share.BrokerClusterName 228 | reqLogger.Info("Updating config " + key + " of cluster" + clusterName) 229 | command := mqAdmin + " " + subCmd + " -c " + clusterName + " -k " + key + " -n " + oldNameServerListStr + " -v " + share.NameServersStr 230 | cmd := exec.Command("sh", mqAdmin, subCmd, "-c", clusterName, "-k", key, "-n", oldNameServerListStr, "-v", share.NameServersStr) 231 | output, err := cmd.Output() 232 | if err != nil { 233 | reqLogger.Error(err, "Update Broker config "+key+" failed of cluster "+clusterName+", command: "+command) 234 | return reconcile.Result{Requeue: true}, err 235 | } 236 | reqLogger.Info("Successfully updated Broker config " + key + " of cluster " + clusterName + ", command: " + command + ", with output: " + string(output)) 237 | } 238 | 239 | } 240 | // Print NameServers IP 241 | for i, value := range instance.Status.NameServers { 242 | reqLogger.Info("NameServers IP " + strconv.Itoa(i) + ": " + value) 243 | } 244 | 245 | runningNameServerNum := getRunningNameServersNum(podList.Items) 246 | if runningNameServerNum == instance.Spec.Size { 247 | share.IsNameServersStrInitialized = true 248 | share.NameServersStr = nameServerListStr // reassign if operator restarts 249 | } 250 | 251 | reqLogger.Info("Share variables", "GroupNum", share.GroupNum, 252 | "NameServersStr", share.NameServersStr, "IsNameServersStrUpdated", share.IsNameServersStrUpdated, 253 | "IsNameServersStrInitialized", share.IsNameServersStrInitialized, "BrokerClusterName", share.BrokerClusterName) 254 | 255 | if requeue { 256 | return reconcile.Result{Requeue: true, RequeueAfter: time.Duration(cons.RequeueIntervalInSecond) * time.Second}, nil 257 | } 258 | 259 | return reconcile.Result{}, nil 260 | } 261 | 262 | func getVolumeClaimTemplates(nameService *rocketmqv1alpha1.NameService) []corev1.PersistentVolumeClaim { 263 | switch nameService.Spec.StorageMode { 264 | case cons.StorageModeStorageClass: 265 | return nameService.Spec.VolumeClaimTemplates 266 | case cons.StorageModeEmptyDir, cons.StorageModeHostPath: 267 | fallthrough 268 | default: 269 | return nil 270 | } 271 | } 272 | 273 | func getVolumes(nameService *rocketmqv1alpha1.NameService) []corev1.Volume { 274 | switch nameService.Spec.StorageMode { 275 | case cons.StorageModeStorageClass: 276 | return nil 277 | case cons.StorageModeEmptyDir: 278 | volumes := []corev1.Volume{{ 279 | Name: nameService.Spec.VolumeClaimTemplates[0].Name, 280 | VolumeSource: corev1.VolumeSource{ 281 | EmptyDir: &corev1.EmptyDirVolumeSource{}}, 282 | }} 283 | return volumes 284 | case cons.StorageModeHostPath: 285 | fallthrough 286 | default: 287 | volumes := []corev1.Volume{{ 288 | Name: nameService.Spec.VolumeClaimTemplates[0].Name, 289 | VolumeSource: corev1.VolumeSource{ 290 | HostPath: &corev1.HostPathVolumeSource{ 291 | Path: nameService.Spec.HostPath, 292 | }}, 293 | }} 294 | return volumes 295 | } 296 | } 297 | 298 | func getNameServers(pods []corev1.Pod) []string { 299 | var nameServers []string 300 | for _, pod := range pods { 301 | if pod.Status.Phase == corev1.PodRunning && 302 | !strings.EqualFold(pod.Status.PodIP, "") { 303 | nameServers = append(nameServers, pod.Status.PodIP) 304 | } 305 | } 306 | return nameServers 307 | } 308 | 309 | func getRunningNameServersNum(pods []corev1.Pod) int32 { 310 | var num int32 = 0 311 | for _, pod := range pods { 312 | if reflect.DeepEqual(pod.Status.Phase, corev1.PodRunning) { 313 | num++ 314 | } 315 | } 316 | return num 317 | } 318 | 319 | func getPodSecurityContext(nameService *rocketmqv1alpha1.NameService) *corev1.PodSecurityContext { 320 | var securityContext = corev1.PodSecurityContext{} 321 | if nameService.Spec.PodSecurityContext != nil { 322 | securityContext = *nameService.Spec.PodSecurityContext 323 | } 324 | return &securityContext 325 | } 326 | 327 | func getContainerSecurityContext(nameService *rocketmqv1alpha1.NameService) *corev1.SecurityContext { 328 | var securityContext = corev1.SecurityContext{} 329 | if nameService.Spec.ContainerSecurityContext != nil { 330 | securityContext = *nameService.Spec.ContainerSecurityContext 331 | } 332 | return &securityContext 333 | } 334 | 335 | func labelsForNameService(name string) map[string]string { 336 | return map[string]string{"app": "name_service", "name_service_cr": name} 337 | } 338 | 339 | func (r *ReconcileNameService) statefulSetForNameService(nameService *rocketmqv1alpha1.NameService) *appsv1.StatefulSet { 340 | ls := labelsForNameService(nameService.Name) 341 | 342 | // After CustomResourceDefinition version upgraded from v1beta1 to v1 343 | // `broker.spec.VolumeClaimTemplates.metadata` declared in yaml will not be stored by kubernetes. 344 | // Here is a temporary repair method: to generate a random name 345 | if strings.EqualFold(nameService.Spec.VolumeClaimTemplates[0].Name, "") { 346 | nameService.Spec.VolumeClaimTemplates[0].Name = uuid.New().String() 347 | } 348 | 349 | dep := &appsv1.StatefulSet{ 350 | ObjectMeta: metav1.ObjectMeta{ 351 | Name: nameService.Name, 352 | Namespace: nameService.Namespace, 353 | }, 354 | Spec: appsv1.StatefulSetSpec{ 355 | Replicas: &nameService.Spec.Size, 356 | Selector: &metav1.LabelSelector{ 357 | MatchLabels: ls, 358 | }, 359 | Template: corev1.PodTemplateSpec{ 360 | ObjectMeta: metav1.ObjectMeta{ 361 | Labels: ls, 362 | Annotations: nameService.Spec.PodAnnotations, 363 | }, 364 | Spec: corev1.PodSpec{ 365 | ServiceAccountName: nameService.Spec.ServiceAccountName, 366 | Affinity: nameService.Spec.Affinity, 367 | Tolerations: nameService.Spec.Tolerations, 368 | NodeSelector: nameService.Spec.NodeSelector, 369 | PriorityClassName: nameService.Spec.PriorityClassName, 370 | HostNetwork: nameService.Spec.HostNetwork, 371 | DNSPolicy: nameService.Spec.DNSPolicy, 372 | ImagePullSecrets: nameService.Spec.ImagePullSecrets, 373 | Containers: []corev1.Container{{ 374 | Resources: nameService.Spec.Resources, 375 | Image: nameService.Spec.NameServiceImage, 376 | // Name must be lower case ! 377 | Name: "name-service", 378 | ImagePullPolicy: nameService.Spec.ImagePullPolicy, 379 | Env: nameService.Spec.Env, 380 | Ports: []corev1.ContainerPort{{ 381 | ContainerPort: cons.NameServiceMainContainerPort, 382 | Name: cons.NameServiceMainContainerPortName, 383 | }}, 384 | VolumeMounts: []corev1.VolumeMount{{ 385 | MountPath: cons.LogMountPath, 386 | Name: nameService.Spec.VolumeClaimTemplates[0].Name, 387 | SubPath: cons.LogSubPathName, 388 | }}, 389 | SecurityContext: getContainerSecurityContext(nameService), 390 | }}, 391 | Volumes: getVolumes(nameService), 392 | SecurityContext: getPodSecurityContext(nameService), 393 | }, 394 | }, 395 | VolumeClaimTemplates: getVolumeClaimTemplates(nameService), 396 | }, 397 | } 398 | // Set Broker instance as the owner and controller 399 | controllerutil.SetControllerReference(nameService, dep, r.scheme) 400 | 401 | return dep 402 | } 403 | -------------------------------------------------------------------------------- /pkg/share/share.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // Package share defines some variables shared by different packages 19 | package share 20 | 21 | var ( 22 | // GroupNum is the number of broker group 23 | GroupNum = 0 24 | 25 | // NameServersStr is the name server list 26 | NameServersStr = "" 27 | 28 | // IsNameServersStrUpdated is whether the name server list is updated 29 | IsNameServersStrUpdated = false 30 | 31 | // IsNameServersStrInitialized is whether the name server list is initialized 32 | IsNameServersStrInitialized = false 33 | 34 | // BrokerClusterName is the broker cluster name 35 | BrokerClusterName = "" 36 | 37 | // svc of controller for brokers 38 | ControllerAccessPoint = "" 39 | ) 40 | -------------------------------------------------------------------------------- /pkg/tool/k8s.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | // Package tool provides tools for operator communicating with K8S cluster 19 | package tool 20 | 21 | import ( 22 | "bytes" 23 | "fmt" 24 | "io" 25 | "os" 26 | "path/filepath" 27 | 28 | "github.com/pkg/errors" 29 | core_v1 "k8s.io/api/core/v1" 30 | "k8s.io/apimachinery/pkg/runtime" 31 | "k8s.io/client-go/kubernetes" 32 | "k8s.io/client-go/rest" 33 | "k8s.io/client-go/tools/clientcmd" 34 | "k8s.io/client-go/tools/remotecommand" 35 | ) 36 | 37 | // K8sClient is a struct which contains the kubernetes.Interface and *rest.Config. 38 | type K8sClient struct { 39 | // kubernetes.Interface should be used instead of kubernets.Inteface for unit test (mocking) 40 | ClientSet kubernetes.Interface 41 | Config *rest.Config 42 | } 43 | 44 | // NewK8sClient is to generate a K8s client for interacting with the K8S cluster. 45 | func NewK8sClient() (*K8sClient, error) { 46 | var kubeconfig string 47 | if kubeConfigPath := os.Getenv("KUBECONFIG"); kubeConfigPath != "" { 48 | kubeconfig = kubeConfigPath // CI process 49 | } else { 50 | kubeconfig = filepath.Join(os.Getenv("HOME"), ".kube", "config") // Development environment 51 | } 52 | 53 | var config *rest.Config 54 | 55 | _, err := os.Stat(kubeconfig) 56 | if err != nil { 57 | // In cluster configuration 58 | config, err = rest.InClusterConfig() 59 | if err != nil { 60 | return nil, err 61 | } 62 | } else { 63 | // Out of cluster configuration 64 | config, err = clientcmd.BuildConfigFromFlags("", kubeconfig) 65 | if err != nil { 66 | return nil, err 67 | } 68 | } 69 | 70 | clientset, err := kubernetes.NewForConfig(config) 71 | if err != nil { 72 | return nil, err 73 | } 74 | var client = &K8sClient{ClientSet: clientset, Config: config} 75 | return client, nil 76 | } 77 | 78 | // Exec enables operator to execute command in the pod's container in the K8S cluster. 79 | // It returns the standard output and the standard error output. 80 | func (client *K8sClient) Exec(namespace, podName, containerName string, command []string, stdin io.Reader) (*bytes.Buffer, *bytes.Buffer, error) { 81 | clientset, config := client.ClientSet, client.Config 82 | 83 | req := clientset.CoreV1().RESTClient().Post(). 84 | Resource("pods"). 85 | Name(podName). 86 | Namespace(namespace). 87 | SubResource("exec") 88 | 89 | scheme := runtime.NewScheme() 90 | if err := core_v1.AddToScheme(scheme); err != nil { 91 | return nil, nil, fmt.Errorf("error adding to scheme: %v", err) 92 | } 93 | 94 | parameterCodec := runtime.NewParameterCodec(scheme) 95 | req.VersionedParams(&core_v1.PodExecOptions{ 96 | Command: command, 97 | Container: containerName, 98 | Stdin: stdin != nil, 99 | Stdout: true, 100 | Stderr: true, 101 | TTY: false, 102 | }, parameterCodec) 103 | 104 | exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL()) 105 | if err != nil { 106 | return nil, nil, errors.Wrap(err, "Could not create SPDY executor") 107 | } 108 | 109 | var stdout, stderr bytes.Buffer 110 | err = exec.Stream(remotecommand.StreamOptions{ 111 | Stdin: stdin, 112 | Stdout: &stdout, 113 | Stderr: &stderr, 114 | Tty: false, 115 | }) 116 | 117 | if err != nil { 118 | return nil, nil, errors.Wrap(err, "Error while exec'ing stream") 119 | } 120 | 121 | return &stdout, &stderr, nil 122 | } 123 | -------------------------------------------------------------------------------- /pkg/tool/resource_name.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package tool 19 | 20 | import "fmt" 21 | 22 | func BuildHeadlessSvcResourceName(name string) string { 23 | return fmt.Sprintf("%s-svc-headless", name) 24 | } 25 | 26 | func BuildSvcResourceName(name string) string { 27 | return fmt.Sprintf("%s-svc", name) 28 | } 29 | -------------------------------------------------------------------------------- /purge-operator.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Licensed to the Apache Software Foundation (ASF) under one or more 4 | # contributor license agreements. See the NOTICE file distributed with 5 | # this work for additional information regarding copyright ownership. 6 | # The ASF licenses this file to You under the Apache License, Version 2.0 7 | # (the "License"); you may not use this file except in compliance with 8 | # the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | 18 | echo "Stopping RocketMQ-Operator..." 19 | 20 | make undeploy 21 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | // Version is the current version of the operator project 4 | var ( 5 | Version = "0.0.1" 6 | ) 7 | --------------------------------------------------------------------------------