Compare commits

...

26 Commits
v0.1.0 ... main

Author SHA1 Message Date
Shubham Gupta 48ca449ecd
go version upgrade
1.16 > 1.20

Signed-off-by: Shubham Gupta <iamshubhamgupta2001@gmail.com>
2023-04-27 10:36:46 +05:30
Shubham Gupta dea0c8657f
go version upgrade
1.16 > 1.20

Signed-off-by: Shubham Gupta <iamshubhamgupta2001@gmail.com>
2023-04-27 10:36:33 +05:30
Abhishek Dubey 3caa4f7009
Added eks cluster creation example (#64)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-12-06 19:12:21 +05:30
Abhishek Dubey 33649c13d7
[BugFix]Fixed cluster creation and validation (#62)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-09-03 20:21:46 +05:30
Abhishek Dubey 5ec4567865
[BugFix] Fixed standalone service creation (#61)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-09-03 18:08:00 +05:30
Abhishek Dubey f322b153d2
Create codeql-analysis.yml 2022-09-03 18:07:19 +05:30
Abhishek Dubey 04d229099f
Create SECURITY.md 2022-09-03 18:06:32 +05:30
Abhishek Dubey 31aec74ac5
Updated CHANGELOG and docs to v0.3.0 (#52)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-03-31 18:12:05 +05:30
Abhishek Dubey 9862fc2397
[Development][Add] Added support for custom config (#51)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-03-31 15:59:59 +05:30
Abhishek Dubey f91b47ae58
Fixed typo mistakes in docs (#49)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-03-01 00:39:26 +05:30
Abhishek Dubey b51a58b136
[Feature][Add] Added PodDisruptionBudget support (#48)
* Added PodDisruptioBudget support

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-21 02:24:08 +05:30
Abhishek Dubey 12468c7850
Added feature for security context (#47)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-20 22:15:52 +05:30
Abhishek Dubey a021bd729a
Update CHANGELOG.md 2022-02-20 20:13:07 +05:30
Abhishek Dubey 5e528dd181
[Feature][Add] Added alerting documentation and feature (#45)
* Added alerting rules for MongoDB

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>

* Updated docs for alerting information

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>

* Added statefulset patch checker

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-20 20:11:50 +05:30
iamabhishek-dubey b8c05f762c Removed extra images
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-17 00:12:39 +05:30
Abhishek Dubey 22601d6b15
[Feature][Add] Added dashboard for MongoDB (#44)
* Added monitoring dashboard for grafana

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>

* Updated documentation for grafana

Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-17 00:07:00 +05:30
Abhishek Dubey d9b9c51801
Added MongoDB dashboard grafana screenshot 2022-02-16 23:51:16 +05:30
Abhishek Dubey 76cd06d634
Added MongoDB dashboard for grafana screenshot 2022-02-16 23:50:43 +05:30
Abhishek Dubey 73423e149f
Updated documentation with CI version (#43)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-16 19:25:28 +05:30
Abhishek Dubey 8e90bc779a
Added MongoDB CI architecture 2022-02-16 17:55:33 +05:30
Abhishek Dubey e9434830d3
Delete mongodb-ci-pipeline.png 2022-02-16 17:55:06 +05:30
Abhishek Dubey 19c4bb29b1
Added Mongo CI pipeline architecture 2022-02-16 17:24:23 +05:30
Abhishek Dubey 300bc85268
Added support for tolerations and priority (#42)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-16 11:12:40 +05:30
Abhishek Dubey 741c6d3d7a
Added affinity and nodeSelector support (#41)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-15 23:54:30 +05:30
Abhishek Dubey 82bc7985b7
[Feature][Add] Added imagePullsecrets support (#38)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-15 23:05:29 +05:30
Abhishek Dubey 92e3879875
Added logic for service and statefulset update (#36)
Signed-off-by: iamabhishek-dubey <abhishekbhardwaj510@gmail.com>
2022-02-15 00:46:41 +05:30
58 changed files with 10209 additions and 424 deletions

View File

@ -24,4 +24,4 @@ extends:
QuayImageName: opstree/mongodb-operator
GithubImageName: ot-container-kit/mongodb-operator/mongodb-operator
BuildDocs: false
AppVersion: "0.1.0"
AppVersion: "0.3.0"

72
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '19 1 * * 4'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# 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
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -1,3 +1,28 @@
### v0.3.0
##### March 31, 2022
#### :tada: Features
- Added dashboard for MongoDB and MongoDB cluster
- Added alerting documentation and feature
- Added support for securityContext
- Added PodDisruptionBudget support
- Added support for custom configuration
### v0.2.0
##### Feburary 16, 2022
#### :tada: Features
- Added ImagePullSecret support
- Added affinity and nodeSelector capability
- Added toleration and priorityClass support
- Updated document with CI process information
#### :beetle: Bug Fixes
- Fixed the patching Kubernetes resources
### v0.1.0
##### Feburary 5, 2022
@ -8,4 +33,3 @@
- Helm chart installation support
- Monitoring support for MongoDB
- Documentation for setup and management

View File

@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.16 as builder
FROM golang:1.20 as builder
WORKDIR /workspace
# Copy the Go Modules manifests

View File

@ -3,7 +3,7 @@
# To re-generate a bundle for another specific version without changing the standard setup, you can:
# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2)
# - use environment variables to overwrite this value (e.g export VERSION=0.0.2)
VERSION ?= v0.1.0
VERSION ?= v0.4.0
# CHANNELS define the bundle channels used in the bundle.
# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable")
@ -90,7 +90,7 @@ test: manifests generate fmt vet envtest ## Run tests.
##@ Build
build: generate fmt vet ## Build manager binary.
build: fmt ## Build manager binary.
go build -o bin/manager main.go
manager:

View File

@ -22,7 +22,7 @@
MongoDB Operator is an operator created in Golang to create, update, and manage MongoDB standalone, replicated, and arbiter replicated setup on Kubernetes and Openshift clusters. This operator is capable of doing the setup for MongoDB with all the required best practices.
For documentation, please refer to https://ot-container-kit.github.io/mongodb-operator/
For documentation, please refer to https://ot-mongodb-operator.netlify.app/
## Architecture
@ -70,7 +70,7 @@ $ helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/
```shell
# Deploy the MongoDB Operator
$ helm upgrade mongodb-operator ot-helm/mongdb-operator \
$ helm upgrade mongodb-operator ot-helm/mongodb-operator \
--install --namespace ot-operators --install
...
Release "mongodb-operator" does not exist. Installing it now.

13
SECURITY.md Normal file
View File

@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 4.0.x | :white_check_mark: |
| 3.0.x | :white_check_mark: |
## Reporting a Vulnerability
If you find any security vulnerability inside the Project, please open a issue at https://github.com/OT-CONTAINER-KIT/mongodb-operator/issues

View File

@ -6,10 +6,15 @@ import (
// KubernetesConfig will be the JSON struct for Basic MongoDB Config
type KubernetesConfig struct {
Image string `json:"image"`
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
ImagePullSecrets *[]corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
Image string `json:"image"`
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
ImagePullSecret *string `json:"imagePullSecret,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Affinity *corev1.Affinity `json:"mongoAffinity,omitempty"`
Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"`
PriorityClassName string `json:"priorityClassName,omitempty"`
SecurityContext *corev1.PodSecurityContext `json:"securityContext,omitempty"`
}
// MongoDBSecurity is the JSON struct for MongoDB security configuration

View File

@ -22,15 +22,15 @@ import (
// MongoDBSpec defines the desired state of MongoDB
type MongoDBSpec struct {
KubernetesConfig KubernetesConfig `json:"kubernetesConfig"`
Storage *Storage `json:"storage,omitempty"`
MongoDBSecurity *MongoDBSecurity `json:"mongoDBSecurity"`
MongoDBMonitoring *MongoDBMonitoring `json:"mongoDBMonitoring,omitempty"`
KubernetesConfig KubernetesConfig `json:"kubernetesConfig"`
Storage *Storage `json:"storage,omitempty"`
MongoDBSecurity *MongoDBSecurity `json:"mongoDBSecurity"`
MongoDBMonitoring *MongoDBMonitoring `json:"mongoDBMonitoring,omitempty"`
MongoDBAdditionalConfig *string `json:"mongoDBAdditionalConfig,omitempty"`
}
// MongoDBStatus defines the observed state of MongoDB
type MongoDBStatus struct {
MongoDB MongoDBSpec `json:"mongodb,omitempty"`
}
//+kubebuilder:object:root=true

View File

@ -22,17 +22,25 @@ import (
// MongoDBClusterSpec defines the desired state of MongoDBCluster
type MongoDBClusterSpec struct {
MongoDBClusterSize *int32 `json:"clusterSize"`
EnableArbiter *bool `json:"enableMongoArbiter,omitempty"`
KubernetesConfig KubernetesConfig `json:"kubernetesConfig"`
Storage *Storage `json:"storage,omitempty"`
MongoDBSecurity *MongoDBSecurity `json:"mongoDBSecurity"`
MongoDBMonitoring *MongoDBMonitoring `json:"mongoDBMonitoring,omitempty"`
MongoDBClusterSize *int32 `json:"clusterSize"`
EnableArbiter *bool `json:"enableMongoArbiter,omitempty"`
KubernetesConfig KubernetesConfig `json:"kubernetesConfig"`
Storage *Storage `json:"storage,omitempty"`
MongoDBSecurity *MongoDBSecurity `json:"mongoDBSecurity"`
MongoDBMonitoring *MongoDBMonitoring `json:"mongoDBMonitoring,omitempty"`
PodDisruptionBudget *MongoDBPodDisruptionBudget `json:"podDisruptionBudget,omitempty"`
MongoDBAdditionalConfig *string `json:"mongoDBAdditionalConfig,omitempty"`
}
// MongoDBPodDisruptionBudget defines the struct for MongoDB cluster
type MongoDBPodDisruptionBudget struct {
Enabled bool `json:"enabled,omitempty"`
MinAvailable *int32 `json:"minAvailable,omitempty"`
MaxUnavailable *int32 `json:"maxUnavailable,omitempty"`
}
// MongoDBClusterStatus defines the observed state of MongoDBCluster
type MongoDBClusterStatus struct {
MongoDBCluster MongoDBClusterSpec `json:"mongodbCluster,omitempty"`
}
//+kubebuilder:object:root=true

View File

@ -1,7 +1,8 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2021.
Copyright 2022.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,15 +22,94 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/api/core/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExistingPasswordSecret) DeepCopyInto(out *ExistingPasswordSecret) {
*out = *in
if in.Name != nil {
in, out := &in.Name, &out.Name
*out = new(string)
**out = **in
}
if in.Key != nil {
in, out := &in.Key, &out.Key
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExistingPasswordSecret.
func (in *ExistingPasswordSecret) DeepCopy() *ExistingPasswordSecret {
if in == nil {
return nil
}
out := new(ExistingPasswordSecret)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesConfig) DeepCopyInto(out *KubernetesConfig) {
*out = *in
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
if in.ImagePullSecret != nil {
in, out := &in.ImagePullSecret, &out.ImagePullSecret
*out = new(string)
**out = **in
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Affinity != nil {
in, out := &in.Affinity, &out.Affinity
*out = new(v1.Affinity)
(*in).DeepCopyInto(*out)
}
if in.Tolerations != nil {
in, out := &in.Tolerations, &out.Tolerations
*out = new([]v1.Toleration)
if **in != nil {
in, out := *in, *out
*out = make([]v1.Toleration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
if in.SecurityContext != nil {
in, out := &in.SecurityContext, &out.SecurityContext
*out = new(v1.PodSecurityContext)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesConfig.
func (in *KubernetesConfig) DeepCopy() *KubernetesConfig {
if in == nil {
return nil
}
out := new(KubernetesConfig)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDB) DeepCopyInto(out *MongoDB) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
}
@ -56,7 +136,7 @@ func (in *MongoDBCluster) DeepCopyInto(out *MongoDBCluster) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
out.Spec = in.Spec
in.Spec.DeepCopyInto(&out.Spec)
out.Status = in.Status
}
@ -113,6 +193,42 @@ func (in *MongoDBClusterList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDBClusterSpec) DeepCopyInto(out *MongoDBClusterSpec) {
*out = *in
if in.MongoDBClusterSize != nil {
in, out := &in.MongoDBClusterSize, &out.MongoDBClusterSize
*out = new(int32)
**out = **in
}
if in.EnableArbiter != nil {
in, out := &in.EnableArbiter, &out.EnableArbiter
*out = new(bool)
**out = **in
}
in.KubernetesConfig.DeepCopyInto(&out.KubernetesConfig)
if in.Storage != nil {
in, out := &in.Storage, &out.Storage
*out = new(Storage)
(*in).DeepCopyInto(*out)
}
if in.MongoDBSecurity != nil {
in, out := &in.MongoDBSecurity, &out.MongoDBSecurity
*out = new(MongoDBSecurity)
(*in).DeepCopyInto(*out)
}
if in.MongoDBMonitoring != nil {
in, out := &in.MongoDBMonitoring, &out.MongoDBMonitoring
*out = new(MongoDBMonitoring)
(*in).DeepCopyInto(*out)
}
if in.PodDisruptionBudget != nil {
in, out := &in.PodDisruptionBudget, &out.PodDisruptionBudget
*out = new(MongoDBPodDisruptionBudget)
(*in).DeepCopyInto(*out)
}
if in.MongoDBAdditionalConfig != nil {
in, out := &in.MongoDBAdditionalConfig, &out.MongoDBAdditionalConfig
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBClusterSpec.
@ -172,9 +288,91 @@ func (in *MongoDBList) DeepCopyObject() runtime.Object {
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDBMonitoring) DeepCopyInto(out *MongoDBMonitoring) {
*out = *in
if in.Resources != nil {
in, out := &in.Resources, &out.Resources
*out = new(v1.ResourceRequirements)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBMonitoring.
func (in *MongoDBMonitoring) DeepCopy() *MongoDBMonitoring {
if in == nil {
return nil
}
out := new(MongoDBMonitoring)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDBPodDisruptionBudget) DeepCopyInto(out *MongoDBPodDisruptionBudget) {
*out = *in
if in.MinAvailable != nil {
in, out := &in.MinAvailable, &out.MinAvailable
*out = new(int32)
**out = **in
}
if in.MaxUnavailable != nil {
in, out := &in.MaxUnavailable, &out.MaxUnavailable
*out = new(int32)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBPodDisruptionBudget.
func (in *MongoDBPodDisruptionBudget) DeepCopy() *MongoDBPodDisruptionBudget {
if in == nil {
return nil
}
out := new(MongoDBPodDisruptionBudget)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDBSecurity) DeepCopyInto(out *MongoDBSecurity) {
*out = *in
in.SecretRef.DeepCopyInto(&out.SecretRef)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBSecurity.
func (in *MongoDBSecurity) DeepCopy() *MongoDBSecurity {
if in == nil {
return nil
}
out := new(MongoDBSecurity)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MongoDBSpec) DeepCopyInto(out *MongoDBSpec) {
*out = *in
in.KubernetesConfig.DeepCopyInto(&out.KubernetesConfig)
if in.Storage != nil {
in, out := &in.Storage, &out.Storage
*out = new(Storage)
(*in).DeepCopyInto(*out)
}
if in.MongoDBSecurity != nil {
in, out := &in.MongoDBSecurity, &out.MongoDBSecurity
*out = new(MongoDBSecurity)
(*in).DeepCopyInto(*out)
}
if in.MongoDBMonitoring != nil {
in, out := &in.MongoDBMonitoring, &out.MongoDBMonitoring
*out = new(MongoDBMonitoring)
(*in).DeepCopyInto(*out)
}
if in.MongoDBAdditionalConfig != nil {
in, out := &in.MongoDBAdditionalConfig, &out.MongoDBAdditionalConfig
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MongoDBSpec.
@ -201,3 +399,28 @@ func (in *MongoDBStatus) DeepCopy() *MongoDBStatus {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Storage) DeepCopyInto(out *Storage) {
*out = *in
if in.AccessModes != nil {
in, out := &in.AccessModes, &out.AccessModes
*out = make([]v1.PersistentVolumeAccessMode, len(*in))
copy(*out, *in)
}
if in.StorageClassName != nil {
in, out := &in.StorageClassName, &out.StorageClassName
*out = new(string)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Storage.
func (in *Storage) DeepCopy() *Storage {
if in == nil {
return nil
}
out := new(Storage)
in.DeepCopyInto(out)
return out
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -97,3 +97,15 @@ rules:
- get
- patch
- update
- apiGroups:
- policy
resources:
- poddisruptionbudgets
verbs:
- create
- delete
- get
- list
- patch
- update
- watch

View File

@ -70,6 +70,10 @@ func (r *MongoDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
if err != nil {
return ctrl.Result{RequeueAfter: time.Second * 10}, err
}
err = k8sgo.CreateMongoStandaloneService(instance)
if err != nil {
return ctrl.Result{RequeueAfter: time.Second * 10}, err
}
mongoDBSTS, err := k8sgo.GetStateFulSet(instance.Namespace, fmt.Sprintf("%s-%s", instance.ObjectMeta.Name, "standalone"))
if err != nil {
return ctrl.Result{RequeueAfter: time.Second * 10}, err
@ -84,10 +88,6 @@ func (r *MongoDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
}
}
}
err = k8sgo.CreateMongoStandaloneService(instance)
if err != nil {
return ctrl.Result{RequeueAfter: time.Second * 10}, err
}
return ctrl.Result{RequeueAfter: time.Second * 10}, nil
}

View File

@ -39,6 +39,7 @@ type MongoDBClusterReconciler struct {
//+kubebuilder:rbac:groups=opstreelabs.in,resources=mongodbclusters,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=opstreelabs.in,resources=mongodbclusters/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=opstreelabs.in,resources=mongodbclusters/finalizers,verbs=update
//+kubebuilder:rbac:groups="policy",resources=poddisruptionbudgets,verbs=get;list;watch;create;update;patch;delete
// Reconcile is part of the main kubernetes reconciliation loop which aims to
func (r *MongoDBClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {

View File

@ -12,25 +12,31 @@ The `values.yaml` file for MongoDB cluster setup can be found [here](https://git
## Parameters for Helm Chart
| **Name** | **Value** | **Description** |
|-------------------------------------------|:------------------------:|---------------------------------------------------|
| `clusterSize` | 3 | Size of the MongoDB cluster |
| `image.name` | quay.io/opstree/mongo | Name of the MongoDB image |
| `image.tag` | v5.0 | Tag for the MongoDB image |
| `image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB |
| `resources` | {} | Request and limits for MongoDB statefulset |
| `storage.enabled` | true | Storage is enabled for MongoDB or not |
| `storage.accessModes` | ["ReadWriteOnce"] | AccessMode for storage provider |
| `storage.storageSize` | 1Gi | Size of storage for MongoDB |
| `storage.storageClass` | gp2 | Name of the storageClass to create storage |
| `mongoDBMonitoring.enabled` | true | MongoDB exporter should be deployed or not |
| `mongoDBMonitoring.image.name` | bitnami/mongodb-exporter | Name of the MongoDB exporter image |
| `mongoDBMonitoring.image.tag` | 0.11.2-debian-10-r382 | Tag of the MongoDB exporter image |
| `mongoDBMonitoring.image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB exporter image |
| `serviceMonitor.enabled` | false | Servicemonitor to monitor MongoDB with Prometheus |
| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. |
| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended |
| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running |
| **Name** | **Value** | **Description** |
|-------------------------------------------|:------------------------:|----------------------------------------------------|
| `clusterSize` | 3 | Size of the MongoDB cluster |
| `image.name` | quay.io/opstree/mongo | Name of the MongoDB image |
| `image.tag` | v5.0 | Tag for the MongoDB image |
| `image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB |
| `image.pullSecret` | "" | Image Pull Secret for private registry |
| `resources` | {} | Request and limits for MongoDB statefulset |
| `storage.enabled` | true | Storage is enabled for MongoDB or not |
| `storage.accessModes` | ["ReadWriteOnce"] | AccessMode for storage provider |
| `storage.storageSize` | 1Gi | Size of storage for MongoDB |
| `storage.storageClass` | gp2 | Name of the storageClass to create storage |
| `mongoDBMonitoring.enabled` | true | MongoDB exporter should be deployed or not |
| `mongoDBMonitoring.image.name` | bitnami/mongodb-exporter | Name of the MongoDB exporter image |
| `mongoDBMonitoring.image.tag` | 0.11.2-debian-10-r382 | Tag of the MongoDB exporter image |
| `mongoDBMonitoring.image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB exporter image |
| `serviceMonitor.enabled` | false | Servicemonitor to monitor MongoDB with Prometheus |
| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. |
| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended |
| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running |
| `nodeSelector` | {} | Nodeselector for the MongoDB statefulset |
| `priorityClassName` | "" | Priority class name for the MongoDB statefulset |
| `affinity` | {} | Affinity for node and pods for MongoDB statefulset |
| `tolerations` | [] | Tolerations for MongoDB statefulset |
| `securityContext` | {} | Security Context for MongoDB pod like:- `fsGroup` |
## Parameters for CRD Object Definition
@ -65,6 +71,54 @@ These are the parameters that are currently supported by the MongoDB operator fo
limits:
cpu: 1
memory: 8Gi
imagePullSecret: regcred
```
`NodeSelector`:- nodeSelector is the simplest recommended form of node selection constraint. nodeSelector is a field of PodSpec. It specifies a map of key-value pairs.
```yaml
kubernetesConfig:
nodeSelector:
beta.kubernetes.io/os: linux
```
`Affinity`:- The affinity/anti-affinity feature, greatly expands the types of constraints you can express. The affinity/anti-affinity language is more expressive. The language offers more matching rules besides exact matches created with a logical AND operation.
```yaml
kubernetesConfig:
mongoAffinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
```
`PriorityClassName`:- A PriorityClass is a non-namespaced object that defines a mapping from a priority class name to the integer value of the priority. The name is specified in the `name` field of the PriorityClass object's metadata. The `value` is specified in the required value field.
```yaml
kubernetesConfig:
priorityClassName: system-node-critical
```
`Tolerations`:- Tolerations are applied to pods, and allow (but do not require) the pods to schedule onto nodes with matching taints.
```yaml
kubernetesConfig:
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
```
`SecurityContext`:- A security context defines privilege and access control settings for a Pod or Container. The security settings that you specify for a Pod apply to all Containers in the Pod.
```yaml
securityContext:
fsGroup: 1001
```
### storage

View File

@ -12,25 +12,30 @@ The `values.yaml` file for MongoDB standalone setup can be found [here](https://
## Parameters for Helm Chart
| **Name** | **Value** | **Description** |
|---------------------------------------------|:------------------------:|----------------------------------------------------|
| `image.name` | quay.io/opstree/mongo | Name of the MongoDB image |
| `image.tag` | v5.0 | Tag for the MongoDB image |
| `image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB |
| `resources` | {} | Request and limits for MongoDB statefulset |
| `storage.enabled` | true | Storage is enabled for MongoDB or not |
| `storage.accessModes` | ["ReadWriteOnce"] | AccessMode for storage provider |
| `storage.storageSize` | 1Gi | Size of storage for MongoDB |
| `storage.storageClass` | gp2 | Name of the storageClass to create storage |
| `mongoDBMonitoring.enabled` | true | MongoDB exporter should be deployed or not |
| `mongoDBMonitoring.image.name` | bitnami/mongodb-exporter | Name of the MongoDB exporter image |
| `mongoDBMonitoring.image.tag` | 0.11.2-debian-10-r382 | Tag of the MongoDB exporter image |
| `mongoDBMonitoring.image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB exporter image |
| `serviceMonitor.enabled` | false | Servicemonitor to monitor MongoDB with Prometheus |
| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. |
| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended |
| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running |
| **Name** | **Value** | **Description** |
|--------------------------------------------|:------------------------:|------------------------------------------------------|
| `image.name` | quay.io/opstree/mongo | Name of the MongoDB image |
| `image.tag` | v5.0 | Tag for the MongoDB image |
| `image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB |
| `image.pullSecret` | "" | Image Pull Secret for private registry |
| `resources` | {} | Request and limits for MongoDB statefulset |
| `storage.enabled` | true | Storage is enabled for MongoDB or not |
| `storage.accessModes` | ["ReadWriteOnce"] | AccessMode for storage provider |
| `storage.storageSize` | 1Gi | Size of storage for MongoDB |
| `storage.storageClass` | gp2 | Name of the storageClass to create storage |
| `mongoDBMonitoring.enabled` | true | MongoDB exporter should be deployed or not |
| `mongoDBMonitoring.image.name` | bitnami/mongodb-exporter | Name of the MongoDB exporter image |
| `mongoDBMonitoring.image.tag` | 0.11.2-debian-10-r382 | Tag of the MongoDB exporter image |
| `mongoDBMonitoring.image.imagePullPolicy` | IfNotPresent | Image Pull Policy of the MongoDB exporter image |
| `serviceMonitor.enabled` | false | Servicemonitor to monitor MongoDB with Prometheus |
| `serviceMonitor.interval` | 30s | Interval at which metrics should be scraped. |
| `serviceMonitor.scrapeTimeout` | 10s | Timeout after which the scrape is ended |
| `serviceMonitor.namespace` | monitoring | Namespace in which Prometheus operator is running |
| `nodeSelector` | {} | Nodeselector for the MongoDB statefulset |
| `priorityClassName` | "" | Priority class name for the MongoDB statefulset |
| `affinity` | {} | Affinity for node and pods for MongoDB statefulset |
| `tolerations` | [] | Tolerations for MongoDB statefulset |
| `securityContext` | {} | Security Context for MongoDB pod like:- `fsGroup` |
## Parameters for CRD Object Definition
@ -56,6 +61,54 @@ These are the parameters that are currently supported by the MongoDB operator fo
limits:
cpu: 1
memory: 8Gi
imagePullSecret: regcred
```
`NodeSelector`:- nodeSelector is the simplest recommended form of node selection constraint. nodeSelector is a field of PodSpec. It specifies a map of key-value pairs.
```yaml
kubernetesConfig:
nodeSelector:
beta.kubernetes.io/os: linux
```
`Affinity`:- The affinity/anti-affinity feature, greatly expands the types of constraints you can express. The affinity/anti-affinity language is more expressive. The language offers more matching rules besides exact matches created with a logical AND operation.
```yaml
kubernetesConfig:
mongoAffinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
```
`PriorityClassName`:- A PriorityClass is a non-namespaced object that defines a mapping from a priority class name to the integer value of the priority. The name is specified in the `name` field of the PriorityClass object's metadata. The `value` is specified in the required value field.
```yaml
kubernetesConfig:
priorityClassName: system-node-critical
```
`Tolerations`:- Tolerations are applied to pods, and allow (but do not require) the pods to schedule onto nodes with matching taints.
```yaml
kubernetesConfig:
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
```
`SecurityContext`:- A security context defines privilege and access control settings for a Pod or Container. The security settings that you specify for a Pod apply to all Containers in the Pod.
```yaml
securityContext:
fsGroup: 1001
```
### storage

View File

@ -0,0 +1,23 @@
---
title: "Continous Integration Pipeline"
weight: 3
linkTitle: "Continous Integration Pipeline"
description: >
Continous Integration Pipeline for MongoDB Operator
---
We are using Azure DevOps pipeline for the Continous Integration in the MongoDB Operator. It checks all the important checks for the corresponding Pull Request. Also, this pipeline is capable of making releases on Quay, Dockerhub, and GitHub.
The pipeline definition can be edited inside the [.azure-pipelines](https://github.com/OT-CONTAINER-KIT/mongodb-operator/tree/main/.azure-pipelines).
![](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/static/mongodb-ci-pipeline.png?raw=true)
Tools used for CI process:-
- **Golang ---> https://go.dev/**
- **Golang CI Lint ---. https://github.com/golangci/golangci-lint**
- **Hadolint ---> https://github.com/hadolint/hadolint**
- **GoSec ---> https://github.com/securego/gosec**
- **Trivy ---> https://github.com/aquasecurity/trivy**

View File

@ -32,7 +32,7 @@ $ helm repo add ot-helm https://ot-container-kit.github.io/helm-charts/
```shell
# Deploy the MongoDB Operator
$ helm install mongodb-operator ot-helm/mongdb-operator \
$ helm install mongodb-operator ot-helm/mongodb-operator \
--namespace ot-operators
...
Release "mongodb-operator" does not exist. Installing it now.

View File

@ -6,4 +6,18 @@ description: >
Monitoring dashboard of MongoDB database for Grafana
---
### Coming Soon
MongoDB grafana dashboard can be found inside [monitoring](https://github.com/OT-CONTAINER-KIT/mongodb-operator/tree/main/monitoring) directory.
The list of available dashboards are:-
- [MongoDB](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/monitoring/dashboards/mongodb.json)
- [MongoDB Overview](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/monitoring/dashboards/mongodb-overview.json)
- [MongoDB Cluster Summary](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/monitoring/dashboards/mongodb-cluster-summary.json)
- [MongoDB Replicaset Cluster](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/monitoring/dashboards/mongodb-replicaset-cluster.json)
## Screenshots
![](https://github.com/OT-CONTAINER-KIT/mongodb-operator/raw/main/static/mongodb-dashboard.png)
![](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/static/mongodb-dashboard-overview.png?raw=true)
![](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/static/mongodb-dashboard-replicaset-overview.png?raw=true)
![](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/static/mongodb-dashboard-cluster-summary-overview.png?raw=true)

View File

@ -8,6 +8,8 @@ description: >
In MongoDB Operator, we are using [mongodb-exporter](https://github.com/percona/mongodb_exporter) to collect the stats, metrics for MongoDB database. This exporter is capable to capture the stats for standalone and cluster mode of MongoDB.
## MongoDB Monitoring
If we are using the `helm` chart for installation purpose, we can simply enable this configuration inside the [values.yaml](https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/mongodb-cluster/values.yaml).
```yaml
@ -71,4 +73,46 @@ spec:
- middleware-production
```
## MongoDB Alerting
Since we are using MongoDB exporter to capture the metrics, we are using the queries available by that exporter to create alerts as well. The alerts are available inside the [alerting](https://github.com/OT-CONTAINER-KIT/mongodb-operator/blob/main/monitoring/alerting/alerts.yaml) directory.
Similar to `ServiceMonitor`, there is another CRD object is available through which we can create Prometheus rules inside Kubernetes cluster using Prometheus Operator.
Example:-
```yaml
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
app: prometheus-mongodb-rules
name: prometheus-mongodb-rules
spec:
groups:
- name: mongodb
rules:
- alert: MongodbDown
expr: mongodb_up == 0
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB Down (instance {{ $labels.instance }})
description: "MongoDB instance is down\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
```
#### Alerts description:-
| **AlertName** | **Description** |
|------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| MongoDB Down | MongoDB instance is down |
| MongoDB replication lag | Mongodb replication lag is more than 10s |
| MongoDB replication Status 3 | MongoDB Replication set member either perform startup self-checks, or transition from completing a rollback or resync |
| MongoDB replication Status 6 | MongoDB Replication set member as seen from another member of the set, is not yet known |
| MongoDB number cursors open | Too many cursors opened by MongoDB for clients (> 10k) |
| MongoDB cursors timeouts | Too many cursors are timing out |
| MongoDB too many connections | Too many connections (> 80%) |
| MongoDB virtual memory usage | High memory usage on MongoDB |

View File

@ -6,6 +6,21 @@ description: >
Changelog version history for MongoDB
---
### v0.2.0
**Feburary 16, 2022**
**🏄 Features**
- Added ImagePullSecret support
- Added affinity and nodeSelector capability
- Added toleration and priorityClass support
- Updated document with CI process information
**🪲 Bug Fixes**
- Fixed the patching Kubernetes resources
### v0.1.0
**Feburary 5, 2022**

View File

@ -0,0 +1,20 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0.6
imagePullPolicy: IfNotPresent
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password
mongoDBAdditionalConfig: mongo-additional-config # name of configmap

View File

@ -0,0 +1,10 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-additional-config
data:
mongo.yaml: |
net:
bindIp: 0.0.0.0
port: 27017

View File

@ -0,0 +1,19 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDB
metadata:
name: mongodb
spec:
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0.6
imagePullPolicy: IfNotPresent
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password
mongoDBAdditionalConfig: mongo-additional-config # name of configmap

View File

@ -0,0 +1,29 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
mongoAffinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: beta.kubernetes.io/os
operator: In
values:
- linux
# nodeSelector: {}
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,21 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDB
metadata:
name: mongodb
spec:
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
nodeSelector:
beta.kubernetes.io/os: linux
# mongoAffinity: {}
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -10,7 +10,7 @@ spec:
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:

View File

@ -0,0 +1,23 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password
podDisruptionBudget:
enabled: true
maxUnavailable: 1
# minAvailable: 1

24
examples/eks-cluster.yaml Normal file
View File

@ -0,0 +1,24 @@
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: operator-testing
region: us-west-2
version: "1.22"
managedNodeGroups:
- name: ng-1
instanceType: t3a.medium
desiredCapacity: 3
volumeSize: 30
ssh:
allow: true
volumeType: gp3
kubernetesNetworkConfig:
ipFamily: IPv4
# ipFamily: IPv6
addons:
- name: vpc-cni
- name: coredns
- name: kube-proxy
iam:
withOIDC: true

View File

@ -10,7 +10,7 @@ spec:
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:

View File

@ -0,0 +1,20 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
imagePullSecret: regcred
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,19 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDB
metadata:
name: mongodb
spec:
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
imagePullSecret: regcred
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,21 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
securityContext:
fsGroup: 1001
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,20 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDB
metadata:
name: mongodb
spec:
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
securityContext:
fsGroup: 1001
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: gp2
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,24 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDBCluster
metadata:
name: mongodb
spec:
clusterSize: 3
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
# priorityClassName: ""
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

View File

@ -0,0 +1,20 @@
---
apiVersion: opstreelabs.in/v1alpha1
kind: MongoDB
metadata:
name: mongodb
spec:
kubernetesConfig:
image: quay.io/opstree/mongo:v5.0
imagePullPolicy: IfNotPresent
priorityClassName: system-node-critical
# tolerations: []
storage:
accessModes: ["ReadWriteOnce"]
storageSize: 1Gi
storageClass: csi-cephfs-sc
mongoDBSecurity:
mongoDBAdminUser: admin
secretRef:
name: mongodb-secret
key: password

82
go.mod
View File

@ -1,16 +1,86 @@
module mongodb-operator
go 1.16
go 1.20
require (
github.com/banzaicloud/k8s-objectmatcher v1.7.0 // indirect
github.com/go-logr/logr v0.4.0 // indirect
github.com/banzaicloud/k8s-objectmatcher v1.7.0
github.com/go-logr/logr v0.4.0
github.com/iamabhishek-dubey/k8s-objectmatcher v1.7.3
github.com/onsi/ginkgo v1.16.4
github.com/onsi/gomega v1.15.0
github.com/thanhpk/randstr v1.0.4 // indirect
go.mongodb.org/mongo-driver v1.8.1 // indirect
k8s.io/api v0.22.1 // indirect
github.com/thanhpk/randstr v1.0.4
go.mongodb.org/mongo-driver v1.8.1
k8s.io/api v0.22.1
k8s.io/apimachinery v0.22.1
k8s.io/client-go v0.22.1
sigs.k8s.io/controller-runtime v0.10.0
)
require (
cloud.google.com/go v0.54.0 // indirect
emperror.dev/errors v0.8.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/zapr v0.4.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/google/go-cmp v0.5.5 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.26.0 // indirect
github.com/prometheus/procfs v0.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.0.2 // indirect
github.com/xdg-go/stringprep v1.0.2 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.26.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiextensions-apiserver v0.22.1 // indirect
k8s.io/component-base v0.22.1 // indirect
k8s.io/klog/v2 v2.9.0 // indirect
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
k8s.io/utils v0.0.0-20210802155522-efc7438f0176 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
)

4
go.sum
View File

@ -75,7 +75,6 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -255,6 +254,8 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iamabhishek-dubey/k8s-objectmatcher v1.7.3 h1:zbW1irjs6VKptsLgPnLIJqIJ2WQkqMBX3yEy564Qtw0=
github.com/iamabhishek-dubey/k8s-objectmatcher v1.7.3/go.mod h1:l4lZ2szZ3WId7GS4W3PKiIeKpuCts5WOikQrclMxrUA=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
@ -417,6 +418,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/thanhpk/randstr v1.0.4 h1:IN78qu/bR+My+gHCvMEXhR/i5oriVHcTB/BJJIRTsNo=
github.com/thanhpk/randstr v1.0.4/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=

View File

@ -68,6 +68,13 @@ func CreateMongoClusterSetup(cr *opstreelabsinv1alpha1.MongoDBCluster) error {
logger.Error(err, "Cannot create cluster StatefulSet for MongoDB")
return err
}
if cr.Spec.PodDisruptionBudget != nil && cr.Spec.PodDisruptionBudget.Enabled {
err = CreateOrUpdatePodDisruption(getPodDisruptionParams(cr))
if err != nil {
logger.Error(err, "Cannot create PodDisruptionBudget for MongoDB")
return err
}
}
return nil
}
@ -125,9 +132,18 @@ func getMongoDBClusterParams(cr *opstreelabsinv1alpha1.MongoDBCluster) statefulS
MongoReplicaSetName: &cr.ObjectMeta.Name,
MongoSetupType: "cluster",
},
Replicas: cr.Spec.MongoDBClusterSize,
Labels: labels,
Annotations: generateAnnotations(),
Replicas: cr.Spec.MongoDBClusterSize,
Labels: labels,
Annotations: generateAnnotations(),
NodeSelector: cr.Spec.KubernetesConfig.NodeSelector,
Affinity: cr.Spec.KubernetesConfig.Affinity,
PriorityClassName: cr.Spec.KubernetesConfig.PriorityClassName,
Tolerations: cr.Spec.KubernetesConfig.Tolerations,
SecurityContext: cr.Spec.KubernetesConfig.SecurityContext,
}
if cr.Spec.KubernetesConfig.ImagePullSecret != nil {
params.ImagePullSecret = cr.Spec.KubernetesConfig.ImagePullSecret
}
if cr.Spec.MongoDBSecurity != nil {
@ -142,6 +158,10 @@ func getMongoDBClusterParams(cr *opstreelabsinv1alpha1.MongoDBCluster) statefulS
params.ContainerParams.MonitoringImage = cr.Spec.MongoDBMonitoring.Image
params.ContainerParams.MonitoringImagePullPolicy = &cr.Spec.MongoDBMonitoring.ImagePullPolicy
}
if cr.Spec.MongoDBAdditionalConfig != nil {
params.ContainerParams.AdditonalConfig = cr.Spec.MongoDBAdditionalConfig
params.AdditionalConfig = cr.Spec.MongoDBAdditionalConfig
}
if cr.Spec.Storage != nil {
params.ContainerParams.PersistenceEnabled = &trueProperty
params.PVCParameters = pvcParameters{
@ -158,3 +178,22 @@ func getMongoDBClusterParams(cr *opstreelabsinv1alpha1.MongoDBCluster) statefulS
}
return params
}
// getPodDisruptionParams is a method to create parameters for pod disruption budget
func getPodDisruptionParams(cr *opstreelabsinv1alpha1.MongoDBCluster) PodDisruptionParameters {
appName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "cluster")
labels := map[string]string{
"app": appName,
"mongodb_setup": "cluster",
"role": "cluster",
}
params := PodDisruptionParameters{
PDBMeta: generateObjectMetaInformation(appName, cr.Namespace, labels, generateAnnotations()),
OwnerDef: mongoClusterAsOwner(cr),
Namespace: cr.Namespace,
Labels: labels,
MinAvailable: cr.Spec.PodDisruptionBudget.MinAvailable,
MaxUnavailable: cr.Spec.PodDisruptionBudget.MaxUnavailable,
}
return params
}

View File

@ -22,11 +22,12 @@ type containerParameters struct {
MonitoringSecret *string
MonitoringResources *corev1.ResourceRequirements
ExtraVolumeMount *corev1.VolumeMount
AdditonalConfig *string
}
// generateContainerDef is to generate container definition for MongoDB
func generateContainerDef(name string, params containerParameters) []corev1.Container {
volumeMounts := getVolumeMount(name, params.PersistenceEnabled)
volumeMounts := getVolumeMount(name, params.PersistenceEnabled, params.AdditonalConfig)
if params.ExtraVolumeMount != nil {
volumeMounts = append(volumeMounts, *params.ExtraVolumeMount)
}
@ -51,7 +52,7 @@ func generateContainerDef(name string, params containerParameters) []corev1.Cont
}
// getVolumeMount is a method to create volume mounting list
func getVolumeMount(name string, persistenceEnabled *bool) []corev1.VolumeMount {
func getVolumeMount(name string, persistenceEnabled *bool, additionalConfig *string) []corev1.VolumeMount {
var volumeMounts []corev1.VolumeMount
if persistenceEnabled != nil && *persistenceEnabled {
volumeMounts = []corev1.VolumeMount{
@ -61,6 +62,13 @@ func getVolumeMount(name string, persistenceEnabled *bool) []corev1.VolumeMount
},
}
}
if additionalConfig != nil {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: "external-config",
MountPath: "/etc/mongo.d/extra",
})
}
return volumeMounts
}

View File

@ -10,8 +10,8 @@ import (
// InitializeMongoDBCluster is a method to create a mongodb cluster
func InitializeMongoDBCluster(cr *opstreelabsinv1alpha1.MongoDBCluster) error {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Cluster Setup")
serviceName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "cluster")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
serviceName := fmt.Sprintf("%s-%s.%s", cr.ObjectMeta.Name, "cluster", cr.Namespace)
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
mongoURL := fmt.Sprintf("mongodb://%s:%s@%s:27017/", cr.Spec.MongoDBSecurity.MongoDBAdminUser, password, serviceName)
mongoParams := mongogo.MongoDBParameters{
@ -33,8 +33,8 @@ func InitializeMongoDBCluster(cr *opstreelabsinv1alpha1.MongoDBCluster) error {
// CheckMongoClusterStateInitialized is a method to check mongodb cluster state
func CheckMongoClusterStateInitialized(cr *opstreelabsinv1alpha1.MongoDBCluster) (bool, error) {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Cluster Setup")
serviceName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "cluster")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
serviceName := fmt.Sprintf("%s-%s.%s", cr.ObjectMeta.Name, "cluster", cr.Namespace)
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
mongoURL := fmt.Sprintf("mongodb://%s:%s@%s:27017/", cr.Spec.MongoDBSecurity.MongoDBAdminUser, password, serviceName)
mongoParams := mongogo.MongoDBParameters{
@ -54,10 +54,10 @@ func CheckMongoClusterStateInitialized(cr *opstreelabsinv1alpha1.MongoDBCluster)
// CreateMongoDBMonitoringUser is a method to create a monitoring user for MongoDB
func CreateMongoDBMonitoringUser(cr *opstreelabsinv1alpha1.MongoDB) error {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Monitoring User")
serviceName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "standalone")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
serviceName := fmt.Sprintf("%s-%s.%s", cr.ObjectMeta.Name, "standalone", cr.Namespace)
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
monitoringPasswordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: fmt.Sprintf("%s-%s", serviceName, "monitoring")}
monitoringPasswordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "standalone-monitoring"), SecretKey: "password"}
monitoringPassword := getMongoDBPassword(monitoringPasswordParams)
mongoURL := fmt.Sprintf("mongodb://%s:%s@%s:27017/", cr.Spec.MongoDBSecurity.MongoDBAdminUser, password, serviceName)
mongoParams := mongogo.MongoDBParameters{
@ -79,10 +79,9 @@ func CreateMongoDBMonitoringUser(cr *opstreelabsinv1alpha1.MongoDB) error {
// CreateMongoDBClusterMonitoringUser is a method to create a monitoring user for MongoDB
func CreateMongoDBClusterMonitoringUser(cr *opstreelabsinv1alpha1.MongoDBCluster) error {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Monitoring User")
serviceName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "cluster")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
monitoringPasswordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: fmt.Sprintf("%s-%s", serviceName, "monitoring")}
monitoringPasswordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "cluster-monitoring"), SecretKey: "password"}
monitoringPassword := getMongoDBPassword(monitoringPasswordParams)
mongoParams := mongogo.MongoDBParameters{
Namespace: cr.Namespace,
@ -112,7 +111,7 @@ func CreateMongoDBClusterMonitoringUser(cr *opstreelabsinv1alpha1.MongoDBCluster
// CheckMongoDBClusterMonitoringUser is a method to check if monitoring user exists in MongoDB
func CheckMongoDBClusterMonitoringUser(cr *opstreelabsinv1alpha1.MongoDBCluster) bool {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Monitoring User")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
monitoringUser := "monitoring"
mongoParams := mongogo.MongoDBParameters{
@ -142,8 +141,8 @@ func CheckMongoDBClusterMonitoringUser(cr *opstreelabsinv1alpha1.MongoDBCluster)
// CheckMonitoringUser is a method to check if monitoring user exists in MongoDB
func CheckMonitoringUser(cr *opstreelabsinv1alpha1.MongoDB) bool {
logger := logGenerator(cr.ObjectMeta.Name, cr.Namespace, "MongoDB Monitoring User")
serviceName := fmt.Sprintf("%s-%s", cr.ObjectMeta.Name, "standalone")
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name}
serviceName := fmt.Sprintf("%s-%s.%s", cr.ObjectMeta.Name, "standalone", cr.Namespace)
passwordParams := secretsParameters{Name: cr.ObjectMeta.Name, Namespace: cr.Namespace, SecretName: *cr.Spec.MongoDBSecurity.SecretRef.Name, SecretKey: *cr.Spec.MongoDBSecurity.SecretRef.Key}
password := getMongoDBPassword(passwordParams)
monitoringUser := "monitoring"
mongoURL := fmt.Sprintf("mongodb://%s:%s@%s:27017/", cr.Spec.MongoDBSecurity.MongoDBAdminUser, password, serviceName)

145
k8sgo/poddisruption.go Normal file
View File

@ -0,0 +1,145 @@
package k8sgo
import (
"context"
"github.com/banzaicloud/k8s-objectmatcher/patch"
policyv1 "k8s.io/api/policy/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
)
// PodDisruptionParameters is an input parameter structure for Pod disruption budget
type PodDisruptionParameters struct {
PDBMeta metav1.ObjectMeta
OwnerDef metav1.OwnerReference
Labels map[string]string
Namespace string
MinAvailable *int32
MaxUnavailable *int32
}
// CreateOrUpdatePodDisruption method will create or update MongoDB PodDisruptionBudgets
func CreateOrUpdatePodDisruption(params PodDisruptionParameters) error {
logger := logGenerator(params.PDBMeta.Name, params.Namespace, "PodDisruptionBudget")
pdbDef := generatePodDisruption(params)
storedPDB, err := getPodDisruption(params.Namespace, params.PDBMeta.Name)
if err != nil {
if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(pdbDef); err != nil {
logger.Error(err, "Unable to patch MongoDB PodDisruptionBudget with comparison object")
return err
}
if errors.IsNotFound(err) {
return createPodDisruption(params.Namespace, pdbDef)
}
return err
}
return patchPodDisruption(storedPDB, pdbDef, params.Namespace)
}
// patchPodDisruption will patch MongoDB Kubernetes PodDisruptionBudgets
func patchPodDisruption(storedPdb *policyv1.PodDisruptionBudget, newPdb *policyv1.PodDisruptionBudget, namespace string) error {
logger := logGenerator(newPdb.Name, namespace, "PodDisruptionBudget")
newPdb.ResourceVersion = storedPdb.ResourceVersion
newPdb.CreationTimestamp = storedPdb.CreationTimestamp
newPdb.ManagedFields = storedPdb.ManagedFields
storedPdb.Kind = "PodDisruptionBudget"
storedPdb.APIVersion = "policy/v1"
patchResult, err := patch.DefaultPatchMaker.Calculate(storedPdb, newPdb,
patch.IgnorePDBSelector(),
patch.IgnoreStatusFields(),
)
if err != nil {
logger.Error(err, "Unable to patch MongoDB PodDisruption with comparison object")
return err
}
if !patchResult.IsEmpty() {
logger.Info("Changes in PodDisruptionBudget Detected, Updating...",
"patch", string(patchResult.Patch),
"Current", string(patchResult.Current),
"Original", string(patchResult.Original),
"Modified", string(patchResult.Modified),
)
for key, value := range storedPdb.Annotations {
if _, present := newPdb.Annotations[key]; !present {
newPdb.Annotations[key] = value
}
}
if err := patch.DefaultAnnotator.SetLastAppliedAnnotation(newPdb); err != nil {
logger.Error(err, "Unable to patch MongoDB PodDisruptionBudget with comparison object")
return err
}
return updatePodDisruption(namespace, newPdb)
}
logger.Info("PodDisruptionBudget is reconciled, nothing to change")
return nil
}
// updatePodDisruption is a method to create Pod disruption budget
func updatePodDisruption(namespace string, pdb *policyv1.PodDisruptionBudget) error {
logger := logGenerator(pdb.Name, namespace, "PodDisruptionBudget")
_, err := generateK8sClient().PolicyV1beta1().PodDisruptionBudgets(namespace).Update(context.TODO(), pdb, metav1.UpdateOptions{})
if err != nil {
logger.Error(err, "MongoDB PodDisruptionBudget update failed")
return err
}
logger.Info("MongoDB PodDisruptionBudget update was successful", "PDB.Spec", pdb.Spec)
return nil
}
// createPodDisruption is a method to create Pod disruption budget
func createPodDisruption(namespace string, pdb *policyv1.PodDisruptionBudget) error {
logger := logGenerator(pdb.Name, namespace, "PodDisruptionBudget")
_, err := generateK8sClient().PolicyV1beta1().PodDisruptionBudgets(namespace).Create(context.TODO(), pdb, metav1.CreateOptions{})
if err != nil {
logger.Error(err, "MongoDB PodDisruptionBudget creation failed")
return err
}
logger.Info("MongoDB PodDisruptionBudget creation was successful", "PDB.Spec", pdb.Spec)
return nil
}
// getPodDisruption is a method to get Pod disruption budget
func getPodDisruption(namespace, name string) (*policyv1.PodDisruptionBudget, error) {
logger := logGenerator(name, namespace, "PodDisruptionBudget")
pdbInfo, err := generateK8sClient().PolicyV1beta1().PodDisruptionBudgets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
if err != nil {
logger.Info("Unable to get pod disruption budget")
return nil, err
}
logger.Info("MongoDB PodDisruptionBudget get action was successful")
return pdbInfo, err
}
// generatePodDisruption is a method to generate Pod disruption budget definiton
func generatePodDisruption(params PodDisruptionParameters) *policyv1.PodDisruptionBudget {
pdbTemplate := &policyv1.PodDisruptionBudget{
TypeMeta: generateMetaInformation("PodDisruptionBudget", "policy/v1beta1"),
ObjectMeta: params.PDBMeta,
Spec: policyv1.PodDisruptionBudgetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: params.Labels,
},
MaxUnavailable: &intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(*params.MaxUnavailable),
},
},
}
if params.MinAvailable != nil {
pdbTemplate.Spec.MinAvailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(*params.MinAvailable),
}
}
if params.MaxUnavailable != nil {
pdbTemplate.Spec.MaxUnavailable = &intstr.IntOrString{
Type: intstr.Int,
IntVal: int32(*params.MaxUnavailable),
}
}
AddOwnerRefToObject(pdbTemplate, params.OwnerDef)
return pdbTemplate
}

View File

@ -16,6 +16,7 @@ type secretsParameters struct {
Annotations map[string]string
SecretsMeta metav1.ObjectMeta
SecretName string
SecretKey string
}
// CreateSecret is a method to create secret
@ -52,7 +53,7 @@ func getMongoDBPassword(params secretsParameters) string {
if err != nil {
logger.Error(err, "Failed in getting existing secret for mongodb admin")
}
value := string(secretName.Data["password"])
value := string(secretName.Data[params.SecretKey])
return value
}

View File

@ -46,16 +46,22 @@ func CreateOrUpdateService(params serviceParameters) error {
// patchService will patch Kubernetes service
func patchService(storedService *corev1.Service, newService *corev1.Service, namespace string) error {
logger := logGenerator(storedService.Name, namespace, "Service")
patchResult, err := patch.DefaultPatchMaker.Calculate(storedService, newService, patch.IgnoreStatusFields())
// adding meta fields
newService.ResourceVersion = storedService.ResourceVersion
newService.CreationTimestamp = storedService.CreationTimestamp
newService.ManagedFields = storedService.ManagedFields
newService.Spec.ClusterIP = storedService.Spec.ClusterIP
patchResult, err := patch.DefaultPatchMaker.Calculate(storedService, newService,
patch.IgnoreStatusFields(),
patch.IgnoreField("kind"),
patch.IgnoreField("apiVersion"),
)
if err != nil {
logger.Error(err, "Unable to patch MongoDB service with comparison object")
return err
}
if !patchResult.IsEmpty() {
newService.Spec.ClusterIP = storedService.Spec.ClusterIP
newService.ResourceVersion = storedService.ResourceVersion
newService.CreationTimestamp = storedService.CreationTimestamp
newService.ManagedFields = storedService.ManagedFields
for key, value := range storedService.Annotations {
if _, present := newService.Annotations[key]; !present {
newService.Annotations[key] = value
@ -128,5 +134,6 @@ func generateServiceDef(params serviceParameters) *corev1.Service {
if params.HeadlessService {
service.Spec.ClusterIP = "None"
}
AddOwnerRefToObject(service, params.OwnerDef)
return service
}

View File

@ -113,11 +113,19 @@ func getMongoDBStandaloneParams(cr *opstreelabsinv1alpha1.MongoDB) statefulSetPa
Resources: cr.Spec.KubernetesConfig.Resources,
MongoSetupType: "standalone",
},
Replicas: &replicas,
Labels: labels,
Annotations: generateAnnotations(),
Replicas: &replicas,
Labels: labels,
Annotations: generateAnnotations(),
NodeSelector: cr.Spec.KubernetesConfig.NodeSelector,
Affinity: cr.Spec.KubernetesConfig.Affinity,
PriorityClassName: cr.Spec.KubernetesConfig.PriorityClassName,
Tolerations: cr.Spec.KubernetesConfig.Tolerations,
SecurityContext: cr.Spec.KubernetesConfig.SecurityContext,
}
if cr.Spec.KubernetesConfig.ImagePullSecret != nil {
params.ImagePullSecret = cr.Spec.KubernetesConfig.ImagePullSecret
}
if cr.Spec.MongoDBSecurity != nil {
params.ContainerParams.MongoDBUser = &cr.Spec.MongoDBSecurity.MongoDBAdminUser
params.ContainerParams.SecretName = cr.Spec.MongoDBSecurity.SecretRef.Name
@ -130,6 +138,10 @@ func getMongoDBStandaloneParams(cr *opstreelabsinv1alpha1.MongoDB) statefulSetPa
params.ContainerParams.MonitoringImage = cr.Spec.MongoDBMonitoring.Image
params.ContainerParams.MonitoringImagePullPolicy = &cr.Spec.MongoDBMonitoring.ImagePullPolicy
}
if cr.Spec.MongoDBAdditionalConfig != nil {
params.ContainerParams.AdditonalConfig = cr.Spec.MongoDBAdditionalConfig
params.AdditionalConfig = cr.Spec.MongoDBAdditionalConfig
}
if cr.Spec.Storage != nil {
params.ContainerParams.PersistenceEnabled = &trueProperty
params.PVCParameters = pvcParameters{

View File

@ -8,21 +8,28 @@ import (
resource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/banzaicloud/k8s-objectmatcher/patch"
"github.com/iamabhishek-dubey/k8s-objectmatcher/patch"
appsv1 "k8s.io/api/apps/v1"
)
// statefulSetParameters is the input struct for MongoDB statefulset
type statefulSetParameters struct {
StatefulSetMeta metav1.ObjectMeta
OwnerDef metav1.OwnerReference
Namespace string
ContainerParams containerParameters
Labels map[string]string
Annotations map[string]string
Replicas *int32
PVCParameters pvcParameters
ExtraVolumes *[]corev1.Volume
StatefulSetMeta metav1.ObjectMeta
OwnerDef metav1.OwnerReference
Namespace string
ContainerParams containerParameters
Labels map[string]string
Annotations map[string]string
Replicas *int32
PVCParameters pvcParameters
ExtraVolumes *[]corev1.Volume
ImagePullSecret *string
Affinity *corev1.Affinity
NodeSelector map[string]string
Tolerations *[]corev1.Toleration
PriorityClassName string
AdditionalConfig *string
SecurityContext *corev1.PodSecurityContext
}
// pvcParameters is the structure for MongoDB PVC
@ -57,15 +64,24 @@ func CreateOrUpdateStateFul(params statefulSetParameters) error {
// patchStateFulSet will patch Statefulset
func patchStateFulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.StatefulSet, namespace string) error {
logger := logGenerator(storedStateful.Name, namespace, "StatefulSet")
patchResult, err := patch.DefaultPatchMaker.Calculate(storedStateful, newStateful)
// adding meta information
newStateful.ResourceVersion = storedStateful.ResourceVersion
newStateful.CreationTimestamp = storedStateful.CreationTimestamp
newStateful.ManagedFields = storedStateful.ManagedFields
patchResult, err := patch.DefaultPatchMaker.Calculate(storedStateful, newStateful,
patch.IgnoreStatusFields(),
patch.IgnoreVolumeClaimTemplateTypeMetaAndStatus(),
patch.IgnorePersistenVolumeFields(),
patch.IgnoreField("kind"),
patch.IgnoreField("apiVersion"),
patch.IgnoreField("metadata"),
)
if err != nil {
logger.Error(err, "Unable to patch mongodb statefulset with comparison object")
return err
}
if !patchResult.IsEmpty() {
newStateful.ResourceVersion = storedStateful.ResourceVersion
newStateful.CreationTimestamp = storedStateful.CreationTimestamp
newStateful.ManagedFields = storedStateful.ManagedFields
logger.Info("Changes in statefulset Detected, Updating...", "patch", string(patchResult.Patch))
for key, value := range storedStateful.Annotations {
if _, present := newStateful.Annotations[key]; !present {
newStateful.Annotations[key] = value
@ -77,6 +93,7 @@ func patchStateFulSet(storedStateful *appsv1.StatefulSet, newStateful *appsv1.St
}
return updateStateFulSet(namespace, newStateful)
}
logger.Info("Reconciliation Complete, no Changes required.")
return nil
}
@ -128,17 +145,27 @@ func generateStatefulSetDef(params statefulSetParameters) *appsv1.StatefulSet {
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{Labels: params.Labels},
Spec: corev1.PodSpec{
Containers: generateContainerDef(params.StatefulSetMeta.Name, params.ContainerParams),
Containers: generateContainerDef(params.StatefulSetMeta.Name, params.ContainerParams),
NodeSelector: params.NodeSelector,
Affinity: params.Affinity,
PriorityClassName: params.PriorityClassName,
SecurityContext: params.SecurityContext,
},
},
},
}
if params.Tolerations != nil {
statefulset.Spec.Template.Spec.Tolerations = *params.Tolerations
}
if params.ContainerParams.PersistenceEnabled != nil && *params.ContainerParams.PersistenceEnabled {
statefulset.Spec.VolumeClaimTemplates = append(statefulset.Spec.VolumeClaimTemplates, generatePersistentVolumeTemplate(params.PVCParameters))
}
if params.ExtraVolumes != nil {
statefulset.Spec.Template.Spec.Volumes = *params.ExtraVolumes
if params.AdditionalConfig != nil {
statefulset.Spec.Template.Spec.Volumes = getAdditionalConfig(params)
}
if params.ImagePullSecret != nil {
statefulset.Spec.Template.Spec.ImagePullSecrets = []corev1.LocalObjectReference{{Name: *params.ImagePullSecret}}
}
AddOwnerRefToObject(statefulset, params.OwnerDef)
return statefulset
@ -148,7 +175,7 @@ func generateStatefulSetDef(params statefulSetParameters) *appsv1.StatefulSet {
func generatePersistentVolumeTemplate(params pvcParameters) corev1.PersistentVolumeClaim {
return corev1.PersistentVolumeClaim{
TypeMeta: generateMetaInformation("PersistentVolumeClaim", "v1"),
ObjectMeta: generateObjectMetaInformation(params.Name, params.Namespace, params.Labels, params.Annotations),
ObjectMeta: metav1.ObjectMeta{Name: params.Name},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: params.AccessModes,
Resources: corev1.ResourceRequirements{
@ -156,6 +183,23 @@ func generatePersistentVolumeTemplate(params pvcParameters) corev1.PersistentVol
corev1.ResourceName(corev1.ResourceStorage): resource.MustParse(params.StorageSize),
},
},
StorageClassName: params.StorageClassName,
},
}
}
// getAdditionalConfig will return the MongoDB additional configuration
func getAdditionalConfig(params statefulSetParameters) []corev1.Volume {
return []corev1.Volume{
{
Name: "external-config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: *params.AdditionalConfig,
},
},
},
},
}
}

View File

@ -0,0 +1,99 @@
---
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
labels:
app: prometheus-mongodb-rules
name: prometheus-mongodb-rules
spec:
groups:
- name: mongodb
rules:
- alert: MongodbDown
expr: mongodb_up == 0
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB Down (instance {{ $labels.instance }})
description: "MongoDB instance is down\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationLag
expr: avg(mongodb_replset_member_optime_date{state="PRIMARY"}) - avg(mongodb_replset_member_optime_date{state="SECONDARY"}) > 10
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication lag (instance {{ $labels.instance }})
description: "Mongodb replication lag is more than 10s\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationStatus3
expr: mongodb_replset_member_state == 3
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication Status 3 (instance {{ $labels.instance }})
description: "MongoDB Replication set member either perform startup self-checks, or transition from completing a rollback or resync\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationStatus6
expr: mongodb_replset_member_state == 6
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication Status 6 (instance {{ $labels.instance }})
description: "MongoDB Replication set member as seen from another member of the set, is not yet known\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationStatus8
expr: mongodb_replset_member_state == 8
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication Status 8 (instance {{ $labels.instance }})
description: "MongoDB Replication set member as seen from another member of the set, is unreachable\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationStatus9
expr: mongodb_replset_member_state == 9
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication Status 9 (instance {{ $labels.instance }})
description: "MongoDB Replication set member is actively performing a rollback. Data is not available for reads\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbReplicationStatus10
expr: mongodb_replset_member_state == 10
for: 0m
labels:
severity: critical
annotations:
summary: MongoDB replication Status 10 (instance {{ $labels.instance }})
description: "MongoDB Replication set member was once in a replica set but was subsequently removed\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbNumberCursorsOpen
expr: mongodb_metrics_cursor_open{state="total_open"} > 10000
for: 2m
labels:
severity: warning
annotations:
summary: MongoDB number cursors open (instance {{ $labels.instance }})
description: "Too many cursors opened by MongoDB for clients (> 10k)\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbCursorsTimeouts
expr: increase(mongodb_metrics_cursor_timed_out_total[1m]) > 100
for: 2m
labels:
severity: warning
annotations:
summary: MongoDB cursors timeouts (instance {{ $labels.instance }})
description: "Too many cursors are timing out\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbTooManyConnections
expr: avg by(instance) (rate(mongodb_connections{state="current"}[1m])) / avg by(instance) (sum (mongodb_connections) by (instance)) * 100 > 80
for: 2m
labels:
severity: warning
annotations:
summary: MongoDB too many connections (instance {{ $labels.instance }})
description: "Too many connections (> 80%)\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"
- alert: MongodbVirtualMemoryUsage
expr: (sum(mongodb_memory{type="virtual"}) BY (instance) / sum(mongodb_memory{type="mapped"}) BY (instance)) > 3
for: 2m
labels:
severity: warning
annotations:
summary: MongoDB virtual memory usage (instance {{ $labels.instance }})
description: "High memory usage\n VALUE = {{ $value }}\n LABELS = {{ $labels }}"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 KiB