[ISSUE #50] Feature add rocketmq exporter to nameserver - #51
Conversation
feature add rocketmq-exporter to cluster
|
Thanks for your contribution~
|
Design: If the exporter is used as an independent pod, when I have multiple nameservers, my exporter does not know which nameserver to connect, so I use exporter as an option of nameserver, deploy it as a sidecar to nameserver。Can you give me some design advice? |
In fact operator maintains a variable in the shared package named |
2) add how to user rocketmq-exporter
…etmq-operator into feature-code-review
ADD exporter image and document. Please check it. I tend to use the exporter as the sidecar of the nameserver. Please check the exporter's dockerfile. Because I tend to adjust the fields in the share package to private, so that multiple clusters can be deployed using one operator. If you still want to deploy the exporter separately, I will do as you say. thanks |
| - name: ROCKETMQ_VERSION | ||
| value: V4_3_2 | ||
| - name: NAMESRV_ADDR | ||
| value: 127.0.0.1:9876 |
There was a problem hiding this comment.
I think it better to init the NAMESRV_ADDR env in nameservice_controller.go
|
This PR has conflicts with the base branch and cannot be merged. Please rebase or merge the base branch into your branch and resolve the conflicts: git fetch origin
git checkout feature-code-review
git rebase origin/main
# resolve conflicts, then:
git push --force-with-leaseThis is a one-time reminder. Feel free to @mention me for a re-review after conflicts are resolved. Automated notification by github-manager-bot |
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
This PR modifies 10 file(s) with 670 lines of diff. No test changes detected — consider adding test coverage.
Automated review by github-manager-bot
Additional notes (not anchored to a changed line)
- [INFO]
README.md:1— Large diff (670 lines). Consider breaking into smaller, focused PRs for easier review. (line outside diff)
| @@ -49,6 +49,17 @@ type NameServiceSpec struct { | |||
| HostPath string `json:"hostPath"` | |||
There was a problem hiding this comment.
No test changes detected alongside source modifications. Consider adding tests to cover the changes.
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
PR received and logged for review. This PR requires detailed code review by a maintainer.
Diff size: 670 lines
Author: linjiemiao (NONE)
Automated review by RockteMQ-AI
| type RocketmqExporter struct { | ||
| Enabled bool `json:"enabled,omitempty"` | ||
| Image string `json:"image,omitempty"` | ||
| ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` |
There was a problem hiding this comment.
RocketmqExporter.Env is tagged json:"env" (no omitempty), meaning it is a required field in JSON serialization. This will cause deserialization errors or validation failures when users omit the env field. It should be json:"env,omitempty" to be consistent with the other optional fields and match the intent of an optional exporter config.
| return specPolicy | ||
| }(nameService.Spec.Exporter.ImagePullPolicy), | ||
| Resources: func(requirements corev1.ResourceRequirements) corev1.ResourceRequirements { | ||
| if requirements.Limits.Memory().IsZero() && requirements.Requests.Memory().IsZero() { |
There was a problem hiding this comment.
The resource default logic checks requirements.Limits.Memory().IsZero() && requirements.Requests.Memory().IsZero(), but if the user specifies CPU limits/requests without memory (or vice versa), the entire requirements struct is replaced with defaults, silently discarding the user's CPU configuration. The check should be done per-resource and only fill in missing individual values, not replace the whole struct.
| return specPolicy | ||
| }(nameService.Spec.Exporter.ImagePullPolicy), | ||
| Resources: func(requirements corev1.ResourceRequirements) corev1.ResourceRequirements { | ||
| if requirements.Limits.Memory().IsZero() && requirements.Requests.Memory().IsZero() { |
There was a problem hiding this comment.
Calling requirements.Limits.Memory() on a nil ResourceList (when Limits is not set at all) will panic. If nameService.Spec.Exporter.Resources.Limits is nil, .Memory() returns a zero quantity via the ResourceList getter, but requirements.Limits itself being nil means the map access is safe in Go — however requirements.Requests being nil is the same case. This is safe in current Go k8s API, but the dual-nil check should be made explicit (check len(requirements.Limits) == 0 && len(requirements.Requests) == 0) to make intent clear and guard against future regressions.
| HostPath string `json:"hostPath"` | ||
| // VolumeClaimTemplates defines the StorageClass | ||
| VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates"` | ||
| // rocketmq exporter |
There was a problem hiding this comment.
The Exporter field uses a value type (RocketmqExporter) rather than a pointer (*RocketmqExporter). Combined with omitempty, a zero-value struct won't be omitted in JSON because omitempty only omits zero values for scalar types and pointers in Go. Users who don't specify an exporter will still have an empty struct serialized, and the Enabled bool defaulting to false is the only guard. Using *RocketmqExporter would make the omission semantics correct and allow distinguishing 'not set' from 'set but disabled'.
| @@ -63,6 +63,9 @@ spec: | |||
| items: | |||
| type: object | |||
| type: array | |||
There was a problem hiding this comment.
The CRD schema defines exporter as type: object with no properties specified. This means Kubernetes will not validate any of the exporter subfields (enabled, image, env, resources, etc.). The schema should be expanded with proper property definitions to enable server-side validation and prevent misconfigured exporter specs from being accepted silently.
| # To have DNS options set along with hostNetwork, you have to specify DNS policy | ||
| # explicitly to 'ClusterFirstWithHostNet'. | ||
| dnsPolicy: ClusterFirstWithHostNet | ||
| # resources describes the compute resource requirements and limits |
There was a problem hiding this comment.
The example file uses image: miaolinjie/rocketmq-exporter:latest (a personal DockerHub repo) while the README example and build script reference apacherocketmq/rocketmq-exporter. Using a personal/unofficial image in example manifests is a supply chain concern and will confuse users. The example should reference the official Apache image or the image built by the provided Dockerfile.
| hostNetwork: true | ||
| # Set DNS policy for the pod. | ||
| # Defaults to "ClusterFirst". | ||
| # Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. |
There was a problem hiding this comment.
The exporter sidecar uses NAMESRV_ADDR: 127.0.0.1:9876 (localhost). This only works correctly when the nameserver pod uses hostNetwork: true (which this example does set). However, the documentation does not make this dependency explicit. If a user enables the exporter without hostNetwork, the exporter will fail to reach the nameserver. This constraint should be documented or enforced/validated in the controller.
| @@ -342,8 +343,42 @@ func (r *ReconcileNameService) statefulSetForNameService(nameService *rocketmqv1 | |||
| VolumeClaimTemplates: getVolumeClaimTemplates(nameService), | |||
| }, | |||
There was a problem hiding this comment.
When nameService.Spec.Exporter.Enabled is toggled from true to false on an existing StatefulSet, the reconciler will not remove the exporter container from the pod template because the existing StatefulSet update path is not shown to handle container list diffing. Verify that the StatefulSet update logic compares and removes containers when the exporter is disabled, otherwise the sidecar will persist until the StatefulSet is deleted and recreated.
| dep.Spec.Template.Spec.Containers = append(dep.Spec.Template.Spec.Containers, exporter) | ||
| } | ||
| // Set Broker instance as the owner and controller | ||
| controllerutil.SetControllerReference(nameService, dep, r.scheme) |
There was a problem hiding this comment.
No test coverage is added for createRocketMQExporterContainer or the exporter injection logic in statefulSetForNameService. Given the resource defaulting logic has edge cases (partial resources, nil maps), unit tests should cover: exporter disabled, exporter enabled with full resources, exporter enabled with no resources (defaults applied), and exporter enabled with partial resources.
| VolumeClaimTemplates []corev1.PersistentVolumeClaim `json:"volumeClaimTemplates"` | ||
| // rocketmq exporter | ||
| Exporter RocketmqExporter `json:"exporter,omitempty"` | ||
| } |
There was a problem hiding this comment.
The RocketmqExporter struct has no Annotations field, but the example YAML (rocketmq_v1alpha1_rocketmq_exporter_cluster.yaml) includes annotations under the exporter spec (for prometheus scraping). These annotations will be silently dropped during deserialization since the type doesn't define them. Either add an Annotations map[string]string field to RocketmqExporter and propagate them to the pod template metadata, or remove them from the example.
No description provided.