From 1f50a2f984cda2be93c35ae2f53a32aa8606718d Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Thu, 7 Nov 2024 19:03:01 +0600 Subject: [PATCH 01/14] Finish standalone Signed-off-by: Neaj Morshad --- .../reconfigure/ms-standalone.yaml | 25 + .../msops-reconfigure-standalone-apply.yaml | 16 + .../msops-reconfigure-standalone.yaml | 14 + docs/guides/mongodb/reconfigure/overview.md | 2 +- docs/guides/mssqlserver/reconfigure/_index.md | 10 + .../mssqlserver/reconfigure/ag_cluster.md | 647 ++++++++++++++++++ .../mssqlserver/reconfigure/overview.md | 54 ++ .../mssqlserver/reconfigure/standalone.md | 526 ++++++++++++++ 8 files changed, 1293 insertions(+), 1 deletion(-) create mode 100644 docs/examples/mssqlserver/reconfigure/ms-standalone.yaml create mode 100644 docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone-apply.yaml create mode 100644 docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone.yaml create mode 100644 docs/guides/mssqlserver/reconfigure/_index.md create mode 100644 docs/guides/mssqlserver/reconfigure/ag_cluster.md create mode 100644 docs/guides/mssqlserver/reconfigure/overview.md create mode 100644 docs/guides/mssqlserver/reconfigure/standalone.md diff --git a/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml b/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml new file mode 100644 index 0000000000..589bd189d1 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml @@ -0,0 +1,25 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: ms-standalone + namespace: demo +spec: + version: "2022-cu12" + configSecret: + name: ms-custom-config + replicas: 1 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone-apply.yaml b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone-apply.yaml new file mode 100644 index 0000000000..0199028a1b --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone-apply.yaml @@ -0,0 +1,16 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone.yaml b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone.yaml new file mode 100644 index 0000000000..5c0f52531a --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/mongodb/reconfigure/overview.md b/docs/guides/mongodb/reconfigure/overview.md index 4975e7588a..50683c37a9 100644 --- a/docs/guides/mongodb/reconfigure/overview.md +++ b/docs/guides/mongodb/reconfigure/overview.md @@ -45,7 +45,7 @@ The Reconfiguring MongoDB process consists of the following steps: 6. When it finds a `MongoDBOpsRequest` CR, it halts the `MongoDB` object which is referred from the `MongoDBOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `MongoDB` object during the reconfiguring process. -7. Then the `KubeDB` Ops-manager operator will replace the existing configuration with the new configuration provided or merge the new configuration with the existing configuration according to the `MogoDBOpsRequest` CR. +7. Then the `KubeDB` Ops-manager operator will replace the existing configuration with the new configuration provided or merge the new configuration with the existing configuration according to the `MongoDBOpsRequest` CR. 8. Then the `KubeDB` Ops-manager operator will restart the related PetSet Pods so that they restart with the new configuration defined in the `MongoDBOpsRequest` CR. diff --git a/docs/guides/mssqlserver/reconfigure/_index.md b/docs/guides/mssqlserver/reconfigure/_index.md new file mode 100644 index 0000000000..3fa45903ac --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure/_index.md @@ -0,0 +1,10 @@ +--- +title: Reconfigure +menu: + docs_{{ .version }}: + identifier: ms-reconfigure + name: Reconfigure + parent: guides-mssqlserver + weight: 67 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure/ag_cluster.md b/docs/guides/mssqlserver/reconfigure/ag_cluster.md new file mode 100644 index 0000000000..82c58f1932 --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure/ag_cluster.md @@ -0,0 +1,647 @@ +--- +title: Reconfigure MSSQLServer Replicaset +menu: + docs_{{ .version }}: + identifier: mg-reconfigure-replicaset + name: Replicaset + parent: mg-reconfigure + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure MSSQLServer Replicaset Database + +This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure a MSSQLServer Replicaset. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [ReplicaSet](/docs/guides/mssqlserver/clustering/replicaset.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + - [Reconfigure Overview](/docs/guides/mssqlserver/reconfigure/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +Now, we are going to deploy a `MSSQLServer` Replicaset using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to reconfigure its configuration. + +### Prepare MSSQLServer Replicaset + +Now, we are going to deploy a `MSSQLServer` Replicaset database with version `4.4.26`. + +### Deploy MSSQLServer + +At first, we will create `mongod.conf` file containing required configuration settings. + +```ini +$ cat mongod.conf +net: + maxIncomingConnections: 10000 +``` +Here, `maxIncomingConnections` is set to `10000`, whereas the default value is `65536`. + +Now, we will create a secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo mg-custom-config --from-file=./mongod.conf +secret/mg-custom-config created +``` + +In this section, we are going to create a MSSQLServer object specifying `spec.configSecret` field to apply this custom configuration. Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: MSSQLServer +metadata: + name: mg-replicaset + namespace: demo +spec: + version: "4.4.26" + replicas: 3 + replicaSet: + name: rs0 + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + configSecret: + name: mg-custom-config +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mg-replicaset-config.yaml +MSSQLServer.kubedb.com/mg-replicaset created +``` + +Now, wait until `mg-replicaset` has status `Ready`. i.e, + +```bash +$ kubectl get mg -n demo +NAME VERSION STATUS AGE +mg-replicaset 4.4.26 Ready 19m +``` + +Now, we will check if the database has started with the custom configuration we have provided. + +First we need to get the username and password to connect to a MSSQLServer instance, +```bash +$ kubectl get secrets -n demo mg-replicaset-auth -o jsonpath='{.data.\username}' | base64 -d +root + +$ kubectl get secrets -n demo mg-replicaset-auth -o jsonpath='{.data.\password}' | base64 -d +nrKuxni0wDSMrgwy +``` + +Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the configuration we have provided. + +```bash +$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet +{ + "argv" : [ + "mongod", + "--dbpath=/data/db", + "--auth", + "--ipv6", + "--bind_ip_all", + "--port=27017", + "--tlsMode=disabled", + "--replSet=rs0", + "--keyFile=/data/configdb/key.txt", + "--clusterAuthMode=keyFile", + "--config=/data/configdb/mongod.conf" + ], + "parsed" : { + "config" : "/data/configdb/mongod.conf", + "net" : { + "bindIp" : "*", + "ipv6" : true, + "maxIncomingConnections" : 10000, + "port" : 27017, + "tls" : { + "mode" : "disabled" + } + }, + "replication" : { + "replSet" : "rs0" + }, + "security" : { + "authorization" : "enabled", + "clusterAuthMode" : "keyFile", + "keyFile" : "/data/configdb/key.txt" + }, + "storage" : { + "dbPath" : "/data/db" + } + }, + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1614668500, 1), + "signature" : { + "hash" : BinData(0,"7sh886HhsNYajGxYGp5Jxi52IzA="), + "keyId" : NumberLong("6934943333319966722") + } + }, + "operationTime" : Timestamp(1614668500, 1) +} +``` + +As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been set to `10000`. + +### Reconfigure using new config secret + +Now we will reconfigure this database to set `maxIncomingConnections` to `20000`. + +Now, we will edit the `mongod.conf` file containing required configuration settings. + +```ini +$ cat mongod.conf +net: + maxIncomingConnections: 20000 +``` + +Then, we will create a new secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo new-custom-config --from-file=./mongod.conf +secret/new-custom-config created +``` + +#### Create MSSQLServerOpsRequest + +Now, we will use this secret to replace the previous secret using a `MSSQLServerOpsRequest` CR. The `MSSQLServerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-reconfigure-replicaset + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mg-replicaset + configuration: + replicaSet: + configSecret: + name: new-custom-config + readinessCriteria: + oplogMaxLagSeconds: 20 + objectsCountDiffPercentage: 10 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `mops-reconfigure-replicaset` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.customConfig.replicaSet.configSecret.name` specifies the name of the new secret. +- `spec.customConfig.arbiter.configSecret.name` could also be specified with a config-secret. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#specreadinesscriteria) on the respective sections to understand the `readinessCriteria`, `timeout` & `apply` fields. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mops-reconfigure-replicaset.yaml +MSSQLServeropsrequest.ops.kubedb.com/mops-reconfigure-replicaset created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will update the `configSecret` of `MSSQLServer` object. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get MSSQLServeropsrequest -n demo +Every 2.0s: kubectl get MSSQLServeropsrequest -n demo +NAME TYPE STATUS AGE +mops-reconfigure-replicaset Reconfigure Successful 113s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. + +```bash +$ kubectl describe MSSQLServeropsrequest -n demo mops-reconfigure-replicaset +Name: mops-reconfigure-replicaset +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-02T07:04:31Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:apply: + f:configuration: + .: + f:replicaSet: + .: + f:configSecret: + .: + f:name: + f:databaseRef: + .: + f:name: + f:readinessCriteria: + .: + f:objectsCountDiffPercentage: + f:oplogMaxLagSeconds: + f:timeout: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-02T07:04:31Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:spec: + f:configuration: + f:replicaSet: + f:podTemplate: + .: + f:controller: + f:metadata: + f:spec: + .: + f:resources: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-02T07:04:31Z + Resource Version: 29869 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-reconfigure-replicaset + UID: 064733d6-19db-4153-82f7-bc0580116ee6 +Spec: + Apply: IfReady + Configuration: + Replica Set: + Config Secret: + Name: new-custom-config + Database Ref: + Name: mg-replicaset + Readiness Criteria: + Objects Count Diff Percentage: 10 + Oplog Max Lag Seconds: 20 + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2021-03-02T07:04:31Z + Message: MSSQLServer ops request is reconfiguring database + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2021-03-02T07:06:21Z + Message: Successfully Reconfigured MSSQLServer + Observed Generation: 1 + Reason: ReconfigureReplicaset + Status: True + Type: ReconfigureReplicaset + Last Transition Time: 2021-03-02T07:06:21Z + Message: Successfully completed the modification process. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 2m55s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-replicaset + Normal PauseDatabase 2m55s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-replicaset + Normal ReconfigureReplicaset 65s KubeDB Ops-manager operator Successfully Reconfigured MSSQLServer + Normal ResumeDatabase 65s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-replicaset + Normal ResumeDatabase 65s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-replicaset + Normal Successful 65s KubeDB Ops-manager operator Successfully Reconfigured Database +``` + +Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the new configuration we have provided. + +```bash +$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet +{ + "argv" : [ + "mongod", + "--dbpath=/data/db", + "--auth", + "--ipv6", + "--bind_ip_all", + "--port=27017", + "--tlsMode=disabled", + "--replSet=rs0", + "--keyFile=/data/configdb/key.txt", + "--clusterAuthMode=keyFile", + "--config=/data/configdb/mongod.conf" + ], + "parsed" : { + "config" : "/data/configdb/mongod.conf", + "net" : { + "bindIp" : "*", + "ipv6" : true, + "maxIncomingConnections" : 20000, + "port" : 27017, + "tls" : { + "mode" : "disabled" + } + }, + "replication" : { + "replSet" : "rs0" + }, + "security" : { + "authorization" : "enabled", + "clusterAuthMode" : "keyFile", + "keyFile" : "/data/configdb/key.txt" + }, + "storage" : { + "dbPath" : "/data/db" + } + }, + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1614668887, 1), + "signature" : { + "hash" : BinData(0,"5q35Y51+YpbVHFKoaU7lUWi38oY="), + "keyId" : NumberLong("6934943333319966722") + } + }, + "operationTime" : Timestamp(1614668887, 1) +} +``` + +As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been changed from `10000` to `20000`. So the reconfiguration of the database is successful. + + +### Reconfigure using apply config + +Now we will reconfigure this database again to set `maxIncomingConnections` to `30000`. This time we won't use a new secret. We will use the `applyConfig` field of the `MSSQLServerOpsRequest`. This will merge the new config in the existing secret. + +#### Create MSSQLServerOpsRequest + +Now, we will use the new configuration in the `applyConfig` field in the `MSSQLServerOpsRequest` CR. The `MSSQLServerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-reconfigure-apply-replicaset + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mg-replicaset + configuration: + replicaSet: + applyConfig: + mongod.conf: |- + net: + maxIncomingConnections: 30000 + readinessCriteria: + oplogMaxLagSeconds: 20 + objectsCountDiffPercentage: 10 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `mops-reconfigure-apply-replicaset` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.configuration.replicaSet.applyConfig` specifies the new configuration that will be merged in the existing secret. +- `spec.customConfig.arbiter.configSecret.name` could also be specified with a config-secret. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#specreadinesscriteria) on the respective sections to understand the `readinessCriteria`, `timeout` & `apply` fields. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mops-reconfigure-apply-replicaset.yaml +MSSQLServeropsrequest.ops.kubedb.com/mops-reconfigure-apply-replicaset created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will merge this new config with the existing configuration. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get MSSQLServeropsrequest -n demo +Every 2.0s: kubectl get MSSQLServeropsrequest -n demo +NAME TYPE STATUS AGE +mops-reconfigure-apply-replicaset Reconfigure Successful 109s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. + +```bash +$ kubectl describe MSSQLServeropsrequest -n demo mops-reconfigure-apply-replicaset +Name: mops-reconfigure-apply-replicaset +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-02T07:09:39Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:apply: + f:configuration: + .: + f:replicaSet: + .: + f:applyConfig: + f:databaseRef: + .: + f:name: + f:readinessCriteria: + .: + f:objectsCountDiffPercentage: + f:oplogMaxLagSeconds: + f:timeout: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-02T07:09:39Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:spec: + f:configuration: + f:replicaSet: + f:podTemplate: + .: + f:controller: + f:metadata: + f:spec: + .: + f:resources: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-02T07:09:39Z + Resource Version: 31005 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-reconfigure-apply-replicaset + UID: 0137442b-1b04-43ed-8de7-ecd913b44065 +Spec: + Apply: IfReady + Configuration: + Replica Set: + Apply Config: net: + maxIncomingConnections: 30000 + + Database Ref: + Name: mg-replicaset + Readiness Criteria: + Objects Count Diff Percentage: 10 + Oplog Max Lag Seconds: 20 + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2021-03-02T07:09:39Z + Message: MSSQLServer ops request is reconfiguring database + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2021-03-02T07:11:14Z + Message: Successfully Reconfigured MSSQLServer + Observed Generation: 1 + Reason: ReconfigureReplicaset + Status: True + Type: ReconfigureReplicaset + Last Transition Time: 2021-03-02T07:11:14Z + Message: Successfully completed the modification process. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 9m20s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-replicaset + Normal PauseDatabase 9m20s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-replicaset + Normal ReconfigureReplicaset 7m45s KubeDB Ops-manager operator Successfully Reconfigured MSSQLServer + Normal ResumeDatabase 7m45s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-replicaset + Normal ResumeDatabase 7m45s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-replicaset + Normal Successful 7m45s KubeDB Ops-manager operator Successfully Reconfigured Database +``` + +Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the new configuration we have provided. + +```bash +$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet +{ + "argv" : [ + "mongod", + "--dbpath=/data/db", + "--auth", + "--ipv6", + "--bind_ip_all", + "--port=27017", + "--tlsMode=disabled", + "--replSet=rs0", + "--keyFile=/data/configdb/key.txt", + "--clusterAuthMode=keyFile", + "--config=/data/configdb/mongod.conf" + ], + "parsed" : { + "config" : "/data/configdb/mongod.conf", + "net" : { + "bindIp" : "*", + "ipv6" : true, + "maxIncomingConnections" : 30000, + "port" : 27017, + "tls" : { + "mode" : "disabled" + } + }, + "replication" : { + "replSet" : "rs0" + }, + "security" : { + "authorization" : "enabled", + "clusterAuthMode" : "keyFile", + "keyFile" : "/data/configdb/key.txt" + }, + "storage" : { + "dbPath" : "/data/db" + } + }, + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1614669580, 1), + "signature" : { + "hash" : BinData(0,"u/xTAa4aW/8bsRvBYPffwQCeTF0="), + "keyId" : NumberLong("6934943333319966722") + } + }, + "operationTime" : Timestamp(1614669580, 1) +} +``` + +As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been changed from `20000` to `30000`. So the reconfiguration of the database using the `applyConfig` field is successful. + + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete mg -n demo mg-replicaset +kubectl delete MSSQLServeropsrequest -n demo mops-reconfigure-replicaset mops-reconfigure-apply-replicaset +``` \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure/overview.md b/docs/guides/mssqlserver/reconfigure/overview.md new file mode 100644 index 0000000000..e92f181ceb --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure/overview.md @@ -0,0 +1,54 @@ +--- +title: Reconfiguring MSSQLServer +menu: + docs_{{ .version }}: + identifier: mg-reconfigure-overview + name: Overview + parent: mg-reconfigure + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfiguring SQL Server + +This guide will give an overview on how KubeDB Ops-manager operator reconfigures `MSSQLServer` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + +## How Reconfiguring MSSQLServer Process Works + +The following diagram shows how KubeDB Ops-manager operator reconfigures `MSSQLServer` database. Open the image in a new tab to see the enlarged version. + +
+  Reconfiguring process of MSSQLServer +
Fig: Reconfiguring process of MSSQLServer
+
+ +The Reconfiguring MSSQLServer process consists of the following steps: + +1. At first, a user creates a `MSSQLServer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `MSSQLServer` CR. + +3. When the operator finds a `MSSQLServer` CR, it creates required number of `PetSets` and related necessary stuff like secrets, services, etc. + +4. Then, in order to reconfigure the `MSSQLServer` database the user creates a `MSSQLServerOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `MSSQLServerOpsRequest` CR. + +6. When it finds a `MSSQLServerOpsRequest` CR, it halts the `MSSQLServer` object which is referred from the `MSSQLServerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `MSSQLServer` object during the reconfiguring process. + +7. Then the `KubeDB` Ops-manager operator will replace the existing configuration with the new configuration provided or merge the new configuration with the existing configuration according to the `MSSQLServerOpsRequest` CR. + +8. Then the `KubeDB` Ops-manager operator will restart the related PetSet Pods so that they restart with the new configuration defined in the `MSSQLServerOpsRequest` CR. + +9. After the successful reconfiguring of the `MSSQLServer`, the `KubeDB` Ops-manager operator resumes the `MSSQLServer` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step-by-step guide on reconfiguring MSSQLServer database using `MSSQLServerOpsRequest` CR. \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure/standalone.md b/docs/guides/mssqlserver/reconfigure/standalone.md new file mode 100644 index 0000000000..72dc0440ec --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure/standalone.md @@ -0,0 +1,526 @@ +--- +title: Reconfigure Standalone MSSQLServer Database +menu: + docs_{{ .version }}: + identifier: ms-reconfigure-standalone + name: Standalone + parent: ms-reconfigure + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure MSSQLServer Standalone Database + +This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure a MSSQLServer standalone database. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + - [Reconfigure Overview](/docs/guides/mssqlserver/reconfigure/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver/reconfigure) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. + +Now, we are going to deploy a `MSSQLServer` standalone using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to reconfigure its configuration. + +### Prepare MSSQLServer Standalone Database + +Now, we are going to deploy a `MSSQLServer` standalone database with version `2022-cu12`. + +### Deploy MSSQLServer standalone + +At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + +Now, we will create `mssql.conf` file containing required configuration settings. + +```ini +$ cat mssql.conf +[memory] +memorylimitmb = 2048 +``` +Here, `memorylimitmb` is set to `2048`, whereas the default value is `12280`. + +Now, we will create a secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo ms-custom-config --from-file=./mssql.conf +secret/ms-custom-config created +``` + +In this section, we are going to create a MSSQLServer object specifying `spec.configSecret` field to apply this custom configuration. Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: ms-standalone + namespace: demo +spec: + version: "2022-cu12" + configSecret: + name: ms-custom-config + replicas: 1 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml +MSSQLServer.kubedb.com/ms-standalone created +``` + +Now, wait until `ms-standalone` has status `Ready`. i.e, + +```bash +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +ms-standalone 4.4.26 Ready 23s +``` + +Now, we will check if the database has started with the custom configuration we have provided. + +First we need to get the username and password to connect to a MSSQLServer instance, +```bash +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\username}' | base64 -d +sa + +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\password}' | base64 -d +SERtEyH1RMMEsvE0 +``` + +Now let's connect to the SQL Server instance and run internal command to check the configuration we have provided. + +```bash +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 2048 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P SERtEyH1RMMEsvE0 +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 2048 + +(1 rows affected) +1> +``` + +As we can see from the configuration of running MSSQLServer, the value of `physical_memory_mb` has been set to `2048`. + +### Reconfigure using new secret + +Now we will reconfigure this database to set `memorylimitmb` to `2560`. + +Now, we will edit the `mssql.conf` file containing required configuration settings. + +```ini +$ cat mssql.conf +[memory] +memorylimitmb = 2560 +``` + +Then, we will create a new secret with this configuration file. + +```bash +$ kubectl create secret generic -n demo new-custom-config --from-file=./mssql.conf +secret/new-custom-config created +``` + +#### Create MSSQLServerOpsRequest + +Now, we will use this secret to replace the previous secret using a `MSSQLServerOpsRequest` CR. The `MSSQLServerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `ms-standalone` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.configuration.configSecret.name` specifies the name of the new secret. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#spectimeout) on the respective sections to understand the `timeout` & `apply` fields. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mops-reconfigure-standalone.yaml +MSSQLServeropsrequest.ops.kubedb.com/mops-reconfigure-standalone created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will update the `configSecret` of `MSSQLServer` object. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get MSSQLServeropsrequest -n demo +Every 2.0s: kubectl get MSSQLServeropsrequest -n demo + +NAME TYPE STATUS AGE +msops-reconfigure-standalone Reconfigure Successful 2m42s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. + +```bash +$ kubectl describe MSSQLServeropsrequest -n demo mops-reconfigure-standalone +Name: msops-reconfigure-standalone +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-07T12:46:35Z + Generation: 1 + Resource Version: 160710 + UID: a3859b47-575c-40a5-84d4-38fb9f37a8ef +Spec: + Apply: IfReady + Configuration: + Config Secret: + Name: new-custom-config + Database Ref: + Name: ms-standalone + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2024-11-07T12:46:35Z + Message: MSSQLServer ops-request has started to reconfigure MSSQLServer nodes + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2024-11-07T12:46:49Z + Message: successfully reconciled the mssqlserver with new configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-07T12:46:54Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-07T12:46:54Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-07T12:47:34Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-07T12:47:39Z + Message: Successfully Restarted Pods after reconfiguration + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2024-11-07T12:47:39Z + Message: Successfully completed reconfiguring for MSSQLServer + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 3m45s KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-reconfigure-standalone + Normal Starting 3m45s KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/ms-standalone + Normal Successful 3m45s KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/ms-standalone for MSSQLServerOpsRequest: msops-reconfigure-standalone + Normal UpdatePetSets 3m31s KubeDB Ops-manager Operator successfully reconciled the mssqlserver with new configuration + Warning get pod; ConditionStatus:True; PodName:ms-standalone-0 3m26s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:ms-standalone-0 + Warning evict pod; ConditionStatus:True; PodName:ms-standalone-0 3m26s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Warning check pod running; ConditionStatus:False; PodName:ms-standalone-0 3m21s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:ms-standalone-0 + Warning check pod running; ConditionStatus:True; PodName:ms-standalone-0 2m46s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Normal RestartPods 2m41s KubeDB Ops-manager Operator Successfully Restarted Pods after reconfiguration + Normal Starting 2m41s KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/ms-standalone + Normal Successful 2m41s KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/ms-standalone for MSSQLServerOpsRequest: msops-reconfigure-standalone +``` + +Now let's connect to SQL Server instance and run a internal command to check the new configuration we have provided. + +```bash +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 2560 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P SERtEyH1RMMEsvE0 +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 2560 + +(1 rows affected) +1> +``` + +As we can see from the configuration of running SQL Server, the value of `physical_memory_mb` has been changed from `2048` to `2560`. So the reconfiguration of the database is successful. + + +### Reconfigure using apply config + +Now we will reconfigure this database again to set `memorylimitmb` to `3072`. This time we won't use a new secret. We will use the `applyConfig` field of the `MSSQLServerOpsRequest`. This will merge the new config in the existing secret. + +#### Create MSSQLServerOpsRequest + +Now, we will use the new configuration in the `applyConfig` field in the `MSSQLServerOpsRequest` CR. The `MSSQLServerOpsRequest` yaml is given below, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are reconfiguring `ms-standalone` database. +- `spec.type` specifies that we are performing `Reconfigure` on our database. +- `spec.configuration.applyConfig` specifies the new configuration that will be merged in the existing secret. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/msops-reconfigure-standalone-apply.yaml +MSSQLServeropsrequest.ops.kubedb.com/msops-reconfigure-standalone-apply created +``` + +#### Verify the new configuration is working + +If everything goes well, `KubeDB` Ops-manager operator will merge this new config with the existing configuration. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get MSSQLServeropsrequest -n demo +Every 2.0s: kubectl get MSSQLServeropsrequest -n demo + +NAME TYPE STATUS AGE +msops-reconfigure-standalone-apply Reconfigure Successful 2m2s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. + +```bash +$ kubectl describe MSSQLServeropsrequest -n demo msops-reconfigure-standalone-apply +Name: msops-reconfigure-standalone-apply +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-07T12:57:43Z + Generation: 1 + Resource Version: 161738 + UID: e9da170c-5d6b-41fd-ae05-b39c6c5f3029 +Spec: + Apply: IfReady + Configuration: + Apply Config: + mssql.conf: [memory] +memorylimitmb = 3072 + Database Ref: + Name: ms-standalone + Timeout: 5m + Type: Reconfigure +Status: + Conditions: + Last Transition Time: 2024-11-07T12:57:43Z + Message: MSSQLServer ops-request has started to reconfigure MSSQLServer nodes + Observed Generation: 1 + Reason: Reconfigure + Status: True + Type: Reconfigure + Last Transition Time: 2024-11-07T12:57:46Z + Message: Successfully prepared user provided custom config secret + Observed Generation: 1 + Reason: PrepareCustomConfig + Status: True + Type: PrepareCustomConfig + Last Transition Time: 2024-11-07T12:57:51Z + Message: successfully reconciled the mssqlserver with new configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-07T12:57:56Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-07T12:57:56Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-07T12:58:31Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-07T12:58:36Z + Message: Successfully Restarted Pods after reconfiguration + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2024-11-07T12:58:36Z + Message: Successfully completed reconfiguring for MSSQLServer + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 2m40s KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-reconfigure-standalone-apply + Normal Starting 2m40s KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/ms-standalone + Normal Successful 2m40s KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/ms-standalone for MSSQLServerOpsRequest: msops-reconfigure-standalone-apply + Normal UpdatePetSets 2m32s KubeDB Ops-manager Operator successfully reconciled the mssqlserver with new configuration + Warning get pod; ConditionStatus:True; PodName:ms-standalone-0 2m27s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:ms-standalone-0 + Warning evict pod; ConditionStatus:True; PodName:ms-standalone-0 2m27s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Warning check pod running; ConditionStatus:False; PodName:ms-standalone-0 2m22s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:ms-standalone-0 + Warning check pod running; ConditionStatus:True; PodName:ms-standalone-0 112s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Normal RestartPods 107s KubeDB Ops-manager Operator Successfully Restarted Pods after reconfiguration + Normal Starting 107s KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/ms-standalone + Normal Successful 107s KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/ms-standalone for MSSQLServerOpsRequest: msops-reconfigure-standalone-apply +``` + +Now let's connect to the SQL Server instance and run a internal command to check the new configuration we have provided. + +```bash +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 3072 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P SERtEyH1RMMEsvE0 +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 3072 + +(1 rows affected) +1> +``` + +As we can see from the configuration of running SQL Server, the value of `physical_memory_mb` has been changed from `2560` to `3072`. So the reconfiguration of the database using the `applyConfig` field is successful. + + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete ms -n demo ms-standalone +kubectl delete MSSQLServeropsrequest -n demo mops-reconfigure-standalone msops-reconfigure-standalone-apply +``` \ No newline at end of file From a6e12b91b9d483fe4241f48b62d3657f5ddc4ce9 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Thu, 7 Nov 2024 19:13:48 +0600 Subject: [PATCH 02/14] Finish reconfigure for ag Signed-off-by: Neaj Morshad --- .../reconfigure/ms-standalone.yaml | 9 + .../msops-reconfigure-ag-apply.yaml | 16 + .../reconfigure/msops-reconfigure-ag.yaml | 14 + .../reconfigure/mssqlserver-ag-cluster.yaml | 40 + .../mssqlserver/reconfigure/ag_cluster.md | 720 ++++++++---------- 5 files changed, 400 insertions(+), 399 deletions(-) create mode 100644 docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag-apply.yaml create mode 100644 docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag.yaml create mode 100644 docs/examples/mssqlserver/reconfigure/mssqlserver-ag-cluster.yaml diff --git a/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml b/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml index 589bd189d1..a6760b97d0 100644 --- a/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml +++ b/docs/examples/mssqlserver/reconfigure/ms-standalone.yaml @@ -14,6 +14,15 @@ spec: kind: Issuer apiGroup: "cert-manager.io" clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation storageType: Durable storage: storageClassName: "standard" diff --git a/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag-apply.yaml b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag-apply.yaml new file mode 100644 index 0000000000..b93d450d54 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag-apply.yaml @@ -0,0 +1,16 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-ag-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mssqlserver-ag-cluster + configuration: + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag.yaml b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag.yaml new file mode 100644 index 0000000000..86d2b8283d --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-ag + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mssqlserver-ag-cluster + configuration: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure/mssqlserver-ag-cluster.yaml b/docs/examples/mssqlserver/reconfigure/mssqlserver-ag-cluster.yaml new file mode 100644 index 0000000000..8407bb6fcf --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure/mssqlserver-ag-cluster.yaml @@ -0,0 +1,40 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssqlserver-ag-cluster + namespace: demo +spec: + version: "2022-cu12" + configSecret: + name: ms-custom-config + replicas: 3 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Developer + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure/ag_cluster.md b/docs/guides/mssqlserver/reconfigure/ag_cluster.md index 82c58f1932..7a2f120a06 100644 --- a/docs/guides/mssqlserver/reconfigure/ag_cluster.md +++ b/docs/guides/mssqlserver/reconfigure/ag_cluster.md @@ -1,9 +1,9 @@ --- -title: Reconfigure MSSQLServer Replicaset +title: Reconfigure MSSQLServer Availability Group menu: docs_{{ .version }}: - identifier: mg-reconfigure-replicaset - name: Replicaset + identifier: mg-reconfigure-ag-cluster + name: Availability Group parent: mg-reconfigure weight: 30 menu_name: docs_{{ .version }} @@ -12,9 +12,9 @@ section_menu_id: guides > New to KubeDB? Please start [here](/docs/README.md). -# Reconfigure MSSQLServer Replicaset Database +# Reconfigure MSSQLServer Availability Group -This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure a MSSQLServer Replicaset. +This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure a SQL Server Availability Group cluster. ## Before You Begin @@ -26,7 +26,7 @@ This guide will show you how to use `KubeDB` Ops-manager operator to reconfigure - You should be familiar with the following `KubeDB` concepts: - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) - - [ReplicaSet](/docs/guides/mssqlserver/clustering/replicaset.md) + - [Availabilty Group](/docs/guides/mssqlserver/clustering/ag_cluster.md) - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) - [Reconfigure Overview](/docs/guides/mssqlserver/reconfigure/overview.md) @@ -37,154 +37,174 @@ $ kubectl create ns demo namespace/demo created ``` -> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver/reconfigure) directory of [kubedb/docs](https://github.com/kubedb/docs) repository. -Now, we are going to deploy a `MSSQLServer` Replicaset using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to reconfigure its configuration. +Now, we are going to deploy a `MSSQLServer` Availability Group using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to reconfigure its configuration. -### Prepare MSSQLServer Replicaset +### Prepare MSSQLServer Availability Group -Now, we are going to deploy a `MSSQLServer` Replicaset database with version `4.4.26`. +Now, we are going to deploy a `MSSQLServer` Availability Group with version `2022-cu12`. -### Deploy MSSQLServer +### Deploy MSSQLServer Availability Group Cluster -At first, we will create `mongod.conf` file containing required configuration settings. +At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` +Now, we will create `mssql.conf` file containing required configuration settings. ```ini -$ cat mongod.conf -net: - maxIncomingConnections: 10000 +$ cat mssql.conf +[memory] +memorylimitmb = 2048 ``` -Here, `maxIncomingConnections` is set to `10000`, whereas the default value is `65536`. +Here, `memorylimitmb` is set to `2048`, whereas the default value is `12280`. Now, we will create a secret with this configuration file. ```bash -$ kubectl create secret generic -n demo mg-custom-config --from-file=./mongod.conf -secret/mg-custom-config created +$ kubectl create secret generic -n demo ms-custom-config --from-file=./mssql.conf +secret/ms-custom-config created ``` In this section, we are going to create a MSSQLServer object specifying `spec.configSecret` field to apply this custom configuration. Below is the YAML of the `MSSQLServer` CR that we are going to create, ```yaml -apiVersion: kubedb.com/v1 +apiVersion: kubedb.com/v1alpha2 kind: MSSQLServer metadata: - name: mg-replicaset + name: mssqlserver-ag-cluster namespace: demo spec: - version: "4.4.26" + version: "2022-cu12" + configSecret: + name: ms-custom-config replicas: 3 - replicaSet: - name: rs0 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation storageType: Durable storage: storageClassName: "standard" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: requests: storage: 1Gi - configSecret: - name: mg-custom-config + deletionPolicy: WipeOut ``` Let's create the `MSSQLServer` CR we have shown above, ```bash -$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mg-replicaset-config.yaml -MSSQLServer.kubedb.com/mg-replicaset created +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mssqlserver-ag-cluster.yaml +MSSQLServer.kubedb.com/mssqlserver-ag-cluster created ``` -Now, wait until `mg-replicaset` has status `Ready`. i.e, +Now, wait until `mssqlserver-ag-cluster` has status `Ready`. i.e, ```bash -$ kubectl get mg -n demo -NAME VERSION STATUS AGE -mg-replicaset 4.4.26 Ready 19m +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +mssqlserver-ag-cluster 2022-cu12 Ready 5m47s ``` Now, we will check if the database has started with the custom configuration we have provided. First we need to get the username and password to connect to a MSSQLServer instance, ```bash -$ kubectl get secrets -n demo mg-replicaset-auth -o jsonpath='{.data.\username}' | base64 -d -root +$ kubectl get secrets -n demo mssqlserver-ag-cluster-auth -o jsonpath='{.data.\username}' | base64 -d +sa -$ kubectl get secrets -n demo mg-replicaset-auth -o jsonpath='{.data.\password}' | base64 -d -nrKuxni0wDSMrgwy +$ kubectl get secrets -n demo mssqlserver-ag-cluster-auth -o jsonpath='{.data.\password}' | base64 -d +gkBGX7RE0ap4yjHt ``` -Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the configuration we have provided. +Now let's connect to the SQL Server instance and run internal command to check the configuration we have provided. ```bash -$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet -{ - "argv" : [ - "mongod", - "--dbpath=/data/db", - "--auth", - "--ipv6", - "--bind_ip_all", - "--port=27017", - "--tlsMode=disabled", - "--replSet=rs0", - "--keyFile=/data/configdb/key.txt", - "--clusterAuthMode=keyFile", - "--config=/data/configdb/mongod.conf" - ], - "parsed" : { - "config" : "/data/configdb/mongod.conf", - "net" : { - "bindIp" : "*", - "ipv6" : true, - "maxIncomingConnections" : 10000, - "port" : 27017, - "tls" : { - "mode" : "disabled" - } - }, - "replication" : { - "replSet" : "rs0" - }, - "security" : { - "authorization" : "enabled", - "clusterAuthMode" : "keyFile", - "keyFile" : "/data/configdb/key.txt" - }, - "storage" : { - "dbPath" : "/data/db" - } - }, - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1614668500, 1), - "signature" : { - "hash" : BinData(0,"7sh886HhsNYajGxYGp5Jxi52IzA="), - "keyId" : NumberLong("6934943333319966722") - } - }, - "operationTime" : Timestamp(1614668500, 1) -} +$ kubectl exec -it -n demo mssqlserver-ag-cluster-0 -c mssql -- bash +mssql@mssqlserver-ag-cluster-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 2048 +mssql@mssqlserver-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P gkBGX7RE0ap4yjHt +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 2048 + +(1 rows affected) ``` -As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been set to `10000`. +As we can see from the configuration of running MSSQLServer, the value of `physical_memory_mb` has been set to `2048`. ### Reconfigure using new config secret -Now we will reconfigure this database to set `maxIncomingConnections` to `20000`. +Now we will reconfigure this database to set `memorylimitmb` to `2560`. -Now, we will edit the `mongod.conf` file containing required configuration settings. +Now, we will edit the `mssql.conf` file containing required configuration settings. ```ini -$ cat mongod.conf -net: - maxIncomingConnections: 20000 +$ cat mssql.conf +[memory] +memorylimitmb = 2560 ``` Then, we will create a new secret with this configuration file. ```bash -$ kubectl create secret generic -n demo new-custom-config --from-file=./mongod.conf +$ kubectl create secret generic -n demo new-custom-config --from-file=./mssql.conf secret/new-custom-config created ``` @@ -196,36 +216,31 @@ Now, we will use this secret to replace the previous secret using a `MSSQLServer apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-reconfigure-replicaset + name: msops-reconfigure-ag namespace: demo spec: type: Reconfigure databaseRef: - name: mg-replicaset + name: mssqlserver-ag-cluster configuration: - replicaSet: - configSecret: - name: new-custom-config - readinessCriteria: - oplogMaxLagSeconds: 20 - objectsCountDiffPercentage: 10 + configSecret: + name: new-custom-config timeout: 5m apply: IfReady ``` Here, -- `spec.databaseRef.name` specifies that we are reconfiguring `mops-reconfigure-replicaset` database. +- `spec.databaseRef.name` specifies that we are reconfiguring `mssqlserver-ag-cluster` database. - `spec.type` specifies that we are performing `Reconfigure` on our database. - `spec.customConfig.replicaSet.configSecret.name` specifies the name of the new secret. -- `spec.customConfig.arbiter.configSecret.name` could also be specified with a config-secret. -- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#specreadinesscriteria) on the respective sections to understand the `readinessCriteria`, `timeout` & `apply` fields. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#spectimeout) on the respective sections to understand the `timeout` & `apply` fields. Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mops-reconfigure-replicaset.yaml -MSSQLServeropsrequest.ops.kubedb.com/mops-reconfigure-replicaset created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag.yaml +MSSQLServeropsrequest.ops.kubedb.com/msops-reconfigure-ag created ``` #### Verify the new configuration is working @@ -236,183 +251,133 @@ Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following co ```bash $ watch kubectl get MSSQLServeropsrequest -n demo -Every 2.0s: kubectl get MSSQLServeropsrequest -n demo -NAME TYPE STATUS AGE -mops-reconfigure-replicaset Reconfigure Successful 113s +NAME TYPE STATUS AGE +msops-reconfigure-ag Reconfigure Successful 4m1s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. ```bash -$ kubectl describe MSSQLServeropsrequest -n demo mops-reconfigure-replicaset -Name: mops-reconfigure-replicaset +$ kubectl describe MSSQLServeropsrequest -n demo msops-reconfigure-ag +Name: msops-reconfigure-ag Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-02T07:04:31Z + Creation Timestamp: 2024-11-11T13:07:49Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:apply: - f:configuration: - .: - f:replicaSet: - .: - f:configSecret: - .: - f:name: - f:databaseRef: - .: - f:name: - f:readinessCriteria: - .: - f:objectsCountDiffPercentage: - f:oplogMaxLagSeconds: - f:timeout: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-02T07:04:31Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:spec: - f:configuration: - f:replicaSet: - f:podTemplate: - .: - f:controller: - f:metadata: - f:spec: - .: - f:resources: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-02T07:04:31Z - Resource Version: 29869 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-reconfigure-replicaset - UID: 064733d6-19db-4153-82f7-bc0580116ee6 + Resource Version: 272883 + UID: 2bbc64b6-9d88-4adc-854e-de444c716f57 Spec: - Apply: IfReady + Apply: IfReady Configuration: - Replica Set: - Config Secret: - Name: new-custom-config + Config Secret: + Name: new-custom-config Database Ref: - Name: mg-replicaset - Readiness Criteria: - Objects Count Diff Percentage: 10 - Oplog Max Lag Seconds: 20 - Timeout: 5m - Type: Reconfigure + Name: mssqlserver-ag-cluster + Timeout: 5m + Type: Reconfigure Status: Conditions: - Last Transition Time: 2021-03-02T07:04:31Z - Message: MSSQLServer ops request is reconfiguring database + Last Transition Time: 2024-11-11T13:07:49Z + Message: MSSQLServer ops-request has started to reconfigure MSSQLServer nodes Observed Generation: 1 Reason: Reconfigure Status: True Type: Reconfigure - Last Transition Time: 2021-03-02T07:06:21Z - Message: Successfully Reconfigured MSSQLServer + Last Transition Time: 2024-11-11T13:07:58Z + Message: successfully reconciled the mssqlserver with new configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-11T13:08:03Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:08:03Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:08:38Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:08:43Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:08:43Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:09:18Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:09:23Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:09:23Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:09:58Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:10:03Z + Message: Successfully Restarted Pods after reconfiguration Observed Generation: 1 - Reason: ReconfigureReplicaset + Reason: RestartPods Status: True - Type: ReconfigureReplicaset - Last Transition Time: 2021-03-02T07:06:21Z - Message: Successfully completed the modification process. + Type: RestartPods + Last Transition Time: 2024-11-11T13:10:03Z + Message: Successfully completed reconfiguring for MSSQLServer Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal PauseDatabase 2m55s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-replicaset - Normal PauseDatabase 2m55s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-replicaset - Normal ReconfigureReplicaset 65s KubeDB Ops-manager operator Successfully Reconfigured MSSQLServer - Normal ResumeDatabase 65s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-replicaset - Normal ResumeDatabase 65s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-replicaset - Normal Successful 65s KubeDB Ops-manager operator Successfully Reconfigured Database ``` -Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the new configuration we have provided. +Now let's connect to SQL Server instance and run internal command to check the new configuration we have provided. ```bash -$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet -{ - "argv" : [ - "mongod", - "--dbpath=/data/db", - "--auth", - "--ipv6", - "--bind_ip_all", - "--port=27017", - "--tlsMode=disabled", - "--replSet=rs0", - "--keyFile=/data/configdb/key.txt", - "--clusterAuthMode=keyFile", - "--config=/data/configdb/mongod.conf" - ], - "parsed" : { - "config" : "/data/configdb/mongod.conf", - "net" : { - "bindIp" : "*", - "ipv6" : true, - "maxIncomingConnections" : 20000, - "port" : 27017, - "tls" : { - "mode" : "disabled" - } - }, - "replication" : { - "replSet" : "rs0" - }, - "security" : { - "authorization" : "enabled", - "clusterAuthMode" : "keyFile", - "keyFile" : "/data/configdb/key.txt" - }, - "storage" : { - "dbPath" : "/data/db" - } - }, - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1614668887, 1), - "signature" : { - "hash" : BinData(0,"5q35Y51+YpbVHFKoaU7lUWi38oY="), - "keyId" : NumberLong("6934943333319966722") - } - }, - "operationTime" : Timestamp(1614668887, 1) -} +$ kubectl exec -it -n demo mssqlserver-ag-cluster-0 -c mssql -- bash +mssql@mssqlserver-ag-cluster-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 2560 +mssql@mssqlserver-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P gkBGX7RE0ap4yjHt +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 2560 + +(1 rows affected) ``` -As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been changed from `10000` to `20000`. So the reconfiguration of the database is successful. - +As we can see from the configuration of running SQL Server, the value of `physical_memory_mb` has been changed from `2048` to `2560`. So the reconfiguration of the database is successful. ### Reconfigure using apply config -Now we will reconfigure this database again to set `maxIncomingConnections` to `30000`. This time we won't use a new secret. We will use the `applyConfig` field of the `MSSQLServerOpsRequest`. This will merge the new config in the existing secret. +Now we will reconfigure this database again to set `memorylimitmb` to `3072`. This time we won't use a new secret. We will use the `applyConfig` field of the `MSSQLServerOpsRequest`. This will merge the new config in the existing secret. #### Create MSSQLServerOpsRequest @@ -422,38 +387,32 @@ Now, we will use the new configuration in the `applyConfig` field in the `MSSQLS apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-reconfigure-apply-replicaset + name: msops-reconfigure-ag-apply namespace: demo spec: type: Reconfigure databaseRef: - name: mg-replicaset + name: mssqlserver-ag-cluster configuration: - replicaSet: - applyConfig: - mongod.conf: |- - net: - maxIncomingConnections: 30000 - readinessCriteria: - oplogMaxLagSeconds: 20 - objectsCountDiffPercentage: 10 + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 timeout: 5m apply: IfReady ``` Here, -- `spec.databaseRef.name` specifies that we are reconfiguring `mops-reconfigure-apply-replicaset` database. +- `spec.databaseRef.name` specifies that we are reconfiguring `mssqlserver-ag-cluster` database. - `spec.type` specifies that we are performing `Reconfigure` on our database. -- `spec.configuration.replicaSet.applyConfig` specifies the new configuration that will be merged in the existing secret. -- `spec.customConfig.arbiter.configSecret.name` could also be specified with a config-secret. -- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#specreadinesscriteria) on the respective sections to understand the `readinessCriteria`, `timeout` & `apply` fields. +- `spec.configuration.applyConfig` specifies the new configuration that will be merged in the existing secret. Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/mops-reconfigure-apply-replicaset.yaml -MSSQLServeropsrequest.ops.kubedb.com/mops-reconfigure-apply-replicaset created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure/msops-reconfigure-ag-apply.yaml +MSSQLServeropsrequest.ops.kubedb.com/msops-reconfigure-ag-apply created ``` #### Verify the new configuration is working @@ -462,186 +421,149 @@ If everything goes well, `KubeDB` Ops-manager operator will merge this new confi Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, +---- + + ```bash $ watch kubectl get MSSQLServeropsrequest -n demo -Every 2.0s: kubectl get MSSQLServeropsrequest -n demo -NAME TYPE STATUS AGE -mops-reconfigure-apply-replicaset Reconfigure Successful 109s +msops-reconfigure-ag-apply Reconfigure Successful 3m34s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to reconfigure the database. ```bash -$ kubectl describe MSSQLServeropsrequest -n demo mops-reconfigure-apply-replicaset -Name: mops-reconfigure-apply-replicaset +$ kubectl describe MSSQLServeropsrequest -n demo msops-reconfigure-ag-apply +Name: msops-reconfigure-ag-apply Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-02T07:09:39Z + Creation Timestamp: 2024-11-11T13:16:11Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:apply: - f:configuration: - .: - f:replicaSet: - .: - f:applyConfig: - f:databaseRef: - .: - f:name: - f:readinessCriteria: - .: - f:objectsCountDiffPercentage: - f:oplogMaxLagSeconds: - f:timeout: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-02T07:09:39Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:spec: - f:configuration: - f:replicaSet: - f:podTemplate: - .: - f:controller: - f:metadata: - f:spec: - .: - f:resources: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-02T07:09:39Z - Resource Version: 31005 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-reconfigure-apply-replicaset - UID: 0137442b-1b04-43ed-8de7-ecd913b44065 + Resource Version: 273846 + UID: 434d35ef-89e5-4d1a-aac2-22941346d77e Spec: - Apply: IfReady + Apply: IfReady Configuration: - Replica Set: - Apply Config: net: - maxIncomingConnections: 30000 - + Apply Config: + mssql.conf: [memory] +memorylimitmb = 3072 Database Ref: - Name: mg-replicaset - Readiness Criteria: - Objects Count Diff Percentage: 10 - Oplog Max Lag Seconds: 20 - Timeout: 5m - Type: Reconfigure + Name: mssqlserver-ag-cluster + Timeout: 5m + Type: Reconfigure Status: Conditions: - Last Transition Time: 2021-03-02T07:09:39Z - Message: MSSQLServer ops request is reconfiguring database + Last Transition Time: 2024-11-11T13:16:11Z + Message: MSSQLServer ops-request has started to reconfigure MSSQLServer nodes Observed Generation: 1 Reason: Reconfigure Status: True Type: Reconfigure - Last Transition Time: 2021-03-02T07:11:14Z - Message: Successfully Reconfigured MSSQLServer + Last Transition Time: 2024-11-11T13:16:14Z + Message: Successfully prepared user provided custom config secret + Observed Generation: 1 + Reason: PrepareCustomConfig + Status: True + Type: PrepareCustomConfig + Last Transition Time: 2024-11-11T13:16:19Z + Message: successfully reconciled the mssqlserver with new configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-11T13:16:24Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:16:24Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:16:59Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-0 + Last Transition Time: 2024-11-11T13:17:04Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:17:04Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:17:39Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-1 + Last Transition Time: 2024-11-11T13:17:44Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:17:44Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:18:19Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-ag-cluster-2 + Last Transition Time: 2024-11-11T13:18:24Z + Message: Successfully Restarted Pods after reconfiguration Observed Generation: 1 - Reason: ReconfigureReplicaset + Reason: RestartPods Status: True - Type: ReconfigureReplicaset - Last Transition Time: 2021-03-02T07:11:14Z - Message: Successfully completed the modification process. + Type: RestartPods + Last Transition Time: 2024-11-11T13:18:24Z + Message: Successfully completed reconfiguring for MSSQLServer Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal PauseDatabase 9m20s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-replicaset - Normal PauseDatabase 9m20s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-replicaset - Normal ReconfigureReplicaset 7m45s KubeDB Ops-manager operator Successfully Reconfigured MSSQLServer - Normal ResumeDatabase 7m45s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-replicaset - Normal ResumeDatabase 7m45s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-replicaset - Normal Successful 7m45s KubeDB Ops-manager operator Successfully Reconfigured Database ``` -Now let's connect to a MSSQLServer instance and run a MSSQLServer internal command to check the new configuration we have provided. +Now let's connect to the SQL Server instance and run a internal command to check the new configuration we have provided. ```bash -$ kubectl exec -n demo mg-replicaset-0 -- mongo admin -u root -p nrKuxni0wDSMrgwy --eval "db._adminCommand( {getCmdLineOpts: 1})" --quiet -{ - "argv" : [ - "mongod", - "--dbpath=/data/db", - "--auth", - "--ipv6", - "--bind_ip_all", - "--port=27017", - "--tlsMode=disabled", - "--replSet=rs0", - "--keyFile=/data/configdb/key.txt", - "--clusterAuthMode=keyFile", - "--config=/data/configdb/mongod.conf" - ], - "parsed" : { - "config" : "/data/configdb/mongod.conf", - "net" : { - "bindIp" : "*", - "ipv6" : true, - "maxIncomingConnections" : 30000, - "port" : 27017, - "tls" : { - "mode" : "disabled" - } - }, - "replication" : { - "replSet" : "rs0" - }, - "security" : { - "authorization" : "enabled", - "clusterAuthMode" : "keyFile", - "keyFile" : "/data/configdb/key.txt" - }, - "storage" : { - "dbPath" : "/data/db" - } - }, - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1614669580, 1), - "signature" : { - "hash" : BinData(0,"u/xTAa4aW/8bsRvBYPffwQCeTF0="), - "keyId" : NumberLong("6934943333319966722") - } - }, - "operationTime" : Timestamp(1614669580, 1) -} +$ kubectl exec -it -n demo mssqlserver-ag-cluster-0 -c mssql -- bash +mssql@mssqlserver-ag-cluster-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[memory] +memorylimitmb = 3072 +mssql@mssqlserver-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P gkBGX7RE0ap4yjHt +1> SELECT physical_memory_kb / 1024 AS physical_memory_mb FROM sys.dm_os_sys_info; +2> go +physical_memory_mb +-------------------- + 3072 + +(1 rows affected) ``` -As we can see from the configuration of ready MSSQLServer, the value of `maxIncomingConnections` has been changed from `20000` to `30000`. So the reconfiguration of the database using the `applyConfig` field is successful. - +As we can see from the configuration of running SQL Server, the value of `physical_memory_mb` has been changed from `2560` to `3072`. So the reconfiguration of the database using the `applyConfig` field is successful. ## Cleaning Up To clean up the Kubernetes resources created by this tutorial, run: ```bash -kubectl delete mg -n demo mg-replicaset -kubectl delete MSSQLServeropsrequest -n demo mops-reconfigure-replicaset mops-reconfigure-apply-replicaset +kubectl delete ms -n demo mssqlserver-ag-cluster +kubectl delete msops -n demo msops-reconfigure-ag msops-reconfigure-ag-apply +kubectl delete issuer -n demo mssqlserver-ca-issuer +kubectl delete secret -n demo mssqlserver-ca +kubectl delete ns demo ``` \ No newline at end of file From 095d329c9386388d61e4b803a62847eb203ccaba Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Tue, 12 Nov 2024 17:36:33 +0600 Subject: [PATCH 03/14] Fix index Signed-off-by: Neaj Morshad --- docs/guides/mssqlserver/autoscaler/_index.md | 2 +- docs/guides/mssqlserver/monitoring/_index.md | 2 +- docs/guides/mssqlserver/pitr/_index.md | 2 +- docs/guides/mssqlserver/reconfigure-tls/_index.md | 10 ++++++++++ docs/guides/mssqlserver/reconfigure/_index.md | 2 +- docs/guides/mssqlserver/restart/_index.md | 2 +- docs/guides/mssqlserver/scaling/_index.md | 2 +- docs/guides/mssqlserver/tls/_Index.md | 2 +- docs/guides/mssqlserver/update-version/_index.md | 10 ++++++++++ docs/guides/mssqlserver/volume-expansion/_index.md | 2 +- 10 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 docs/guides/mssqlserver/reconfigure-tls/_index.md create mode 100644 docs/guides/mssqlserver/update-version/_index.md diff --git a/docs/guides/mssqlserver/autoscaler/_index.md b/docs/guides/mssqlserver/autoscaler/_index.md index b6fdc08188..a6694c0b45 100644 --- a/docs/guides/mssqlserver/autoscaler/_index.md +++ b/docs/guides/mssqlserver/autoscaler/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-autoscaling name: Autoscaling parent: guides-mssqlserver - weight: 46 + weight: 70 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/mssqlserver/monitoring/_index.md b/docs/guides/mssqlserver/monitoring/_index.md index a7c806c4cc..f13e64bc7b 100755 --- a/docs/guides/mssqlserver/monitoring/_index.md +++ b/docs/guides/mssqlserver/monitoring/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-monitoring name: Monitoring parent: guides-mssqlserver - weight: 50 + weight: 90 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/mssqlserver/pitr/_index.md b/docs/guides/mssqlserver/pitr/_index.md index 8f53fdd34e..2e4e0b2004 100644 --- a/docs/guides/mssqlserver/pitr/_index.md +++ b/docs/guides/mssqlserver/pitr/_index.md @@ -5,6 +5,6 @@ menu: identifier: pitr-mssqlserver name: Point-in-time Recovery parent: guides-mssqlserver - weight: 42 + weight: 45 menu_name: docs_{{ .version }} --- \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure-tls/_index.md b/docs/guides/mssqlserver/reconfigure-tls/_index.md new file mode 100644 index 0000000000..2d27c475d3 --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure-tls/_index.md @@ -0,0 +1,10 @@ +--- +title: Reconfigure MSSQLServer TLS/SSL +menu: + docs_{{ .version }}: + identifier: ms-reconfigure-tls + name: Reconfigure TLS/SSL + parent: guides-mssqlserver + weight: 80 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/mssqlserver/reconfigure/_index.md b/docs/guides/mssqlserver/reconfigure/_index.md index 3fa45903ac..923c470deb 100644 --- a/docs/guides/mssqlserver/reconfigure/_index.md +++ b/docs/guides/mssqlserver/reconfigure/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-reconfigure name: Reconfigure parent: guides-mssqlserver - weight: 67 + weight: 75 menu_name: docs_{{ .version }} --- \ No newline at end of file diff --git a/docs/guides/mssqlserver/restart/_index.md b/docs/guides/mssqlserver/restart/_index.md index cbd526b865..afdebf6a84 100644 --- a/docs/guides/mssqlserver/restart/_index.md +++ b/docs/guides/mssqlserver/restart/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-restart name: Restart parent: guides-mssqlserver - weight: 46 + weight: 85 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/mssqlserver/scaling/_index.md b/docs/guides/mssqlserver/scaling/_index.md index fcf648eaf6..e2c492a678 100644 --- a/docs/guides/mssqlserver/scaling/_index.md +++ b/docs/guides/mssqlserver/scaling/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-scaling name: Scaling Microsoft SQL Server parent: guides-mssqlserver - weight: 43 + weight: 55 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/mssqlserver/tls/_Index.md b/docs/guides/mssqlserver/tls/_Index.md index bf62d65dd1..84c6852db5 100644 --- a/docs/guides/mssqlserver/tls/_Index.md +++ b/docs/guides/mssqlserver/tls/_Index.md @@ -5,6 +5,6 @@ menu: identifier: ms-tls name: TLS/SSL Encryption parent: guides-mssqlserver - weight: 45 + weight: 65 menu_name: docs_{{ .version }} --- diff --git a/docs/guides/mssqlserver/update-version/_index.md b/docs/guides/mssqlserver/update-version/_index.md new file mode 100644 index 0000000000..e386d1eec4 --- /dev/null +++ b/docs/guides/mssqlserver/update-version/_index.md @@ -0,0 +1,10 @@ +--- +title: Updating MSSQLServer +menu: + docs_{{ .version }}: + identifier: mssql-updating + name: UpdateVersion + parent: guides-mssqlserver + weight: 50 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/mssqlserver/volume-expansion/_index.md b/docs/guides/mssqlserver/volume-expansion/_index.md index 899484bfd1..e8ef67d309 100644 --- a/docs/guides/mssqlserver/volume-expansion/_index.md +++ b/docs/guides/mssqlserver/volume-expansion/_index.md @@ -5,6 +5,6 @@ menu: identifier: ms-volume-expansion name: Volume Expansion parent: guides-mssqlserver - weight: 42 + weight: 60 menu_name: docs_{{ .version }} --- From 2ad955def5e63438a679c3ed3896ed23ce5cfb32 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Tue, 12 Nov 2024 18:05:15 +0600 Subject: [PATCH 04/14] Update images Signed-off-by: Neaj Morshad --- .../mssqlserver/reconfigure/ag_cluster.md | 4 ++-- docs/guides/mssqlserver/reconfigure/overview.md | 6 +++--- .../mssqlserver/ms-reconfigure.png | Bin 0 -> 68290 bytes .../mssqlserver/ms-update-version.png | Bin 0 -> 75257 bytes 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 docs/images/day-2-operation/mssqlserver/ms-reconfigure.png create mode 100644 docs/images/day-2-operation/mssqlserver/ms-update-version.png diff --git a/docs/guides/mssqlserver/reconfigure/ag_cluster.md b/docs/guides/mssqlserver/reconfigure/ag_cluster.md index 7a2f120a06..1ce0a35ffa 100644 --- a/docs/guides/mssqlserver/reconfigure/ag_cluster.md +++ b/docs/guides/mssqlserver/reconfigure/ag_cluster.md @@ -2,9 +2,9 @@ title: Reconfigure MSSQLServer Availability Group menu: docs_{{ .version }}: - identifier: mg-reconfigure-ag-cluster + identifier: ms-reconfigure-ag-cluster name: Availability Group - parent: mg-reconfigure + parent: ms-reconfigure weight: 30 menu_name: docs_{{ .version }} section_menu_id: guides diff --git a/docs/guides/mssqlserver/reconfigure/overview.md b/docs/guides/mssqlserver/reconfigure/overview.md index e92f181ceb..d24dd5e899 100644 --- a/docs/guides/mssqlserver/reconfigure/overview.md +++ b/docs/guides/mssqlserver/reconfigure/overview.md @@ -2,9 +2,9 @@ title: Reconfiguring MSSQLServer menu: docs_{{ .version }}: - identifier: mg-reconfigure-overview + identifier: ms-reconfigure-overview name: Overview - parent: mg-reconfigure + parent: ms-reconfigure weight: 10 menu_name: docs_{{ .version }} section_menu_id: guides @@ -27,7 +27,7 @@ This guide will give an overview on how KubeDB Ops-manager operator reconfigures The following diagram shows how KubeDB Ops-manager operator reconfigures `MSSQLServer` database. Open the image in a new tab to see the enlarged version.
-  Reconfiguring process of MSSQLServer +  Reconfiguring process of MSSQLServer
Fig: Reconfiguring process of MSSQLServer
diff --git a/docs/images/day-2-operation/mssqlserver/ms-reconfigure.png b/docs/images/day-2-operation/mssqlserver/ms-reconfigure.png new file mode 100644 index 0000000000000000000000000000000000000000..af8b0b93f60f029f1649fba239f71d4bc1560710 GIT binary patch literal 68290 zcmeFZ^;?ut*ES3YN;fjfAgMIW7<9;xN_Qh6p>&6oNHYv2DIuUBEzQu4G>CLFz|aUt z*LRKH_xn75z;_()FYgcHadFJ-Ywxw!I`_HGwKn0Z%5o%x_X)AEut;9WORHmH;i9mx zaIo-i1HWkjed`1MBXE@0bHTzQqQd;c#!5{C0l&m{QI~^Zl?;M6fCpSFNhL`vtg>jL zOH({7Y(kwE(vq5<*xOem$>1^H-N+`E9-n((C|=zIi@)Tr{%-n74Ngf%RfucLvP}2H zb4GU7u||KbO?;xqJc@h&wTP`M5yM`+Z-Dhj^e%cW>_eU#f9s=T85WT;i#rBiS-VbQ z*-Wjtrc<2a)ep_#vTZ&JsiO|1Rk_*|nnQp3U58wc8k*7h8zlu=h1w^sIy#L<*Ejyp z@tK0iVgK*P|4%lEXAHoMWXVJSZ$M^-KOggUf0ch&ee=#MV&oimHNROj7=kj=%;29o zTU~vFKibZJ;mPyA_TZajz9>mjUiy6H5bu`EmPX(`hcIc)Z7!91XyZqd`Fid5dwAVc z|7+hWi64TXTqJlr!Yjff)2fb}q4HF1_yySiGp2N(Dy$kr+Y%-;;n~ODZx=w&^98?} zv%W8a{FlSbA0`8GPS2~?RZ}JxWQ|P`@*Sf<@NsOxHyMVvX!l;9p_oH-gc0#m6`BI~lOv7?%r(3ECg+`n?%3zm?b}W4m@XgIaH|5-EWd}0{ZdUpEab? zH1=9(Tu8N&itMNK{4?Kgcm2Jg!harfDOM$q=m>`zT3;O0toktJ@ZDT-Simupn+_e> zv!PhKa;AQKPH6k7=q8+{()>uK)LxUww?rvsx|%HK70SMTb}21nW9RaO?YX;gE2Tb{ zM+P}8Os`G!U!cY^uzx?pd1;atCC^#F%cb&3%_#lj)@{>{8hqL0rOR>6o4!W0SoOg3 z0+Ne)%kJgleZc~*I_FPH?zYg)4_Cn;o@<$8pQ=gFk=-XhhTA)yIQ3TraHkIUdYi8G ziAITu$z!SNJxREV_9?HP34>Ipbq_^ESYUelXfO|cq56&mV;73>k z1q+3H;6dfxF=Z~^9CH4&)V71l;p!}`!+yaFWUVY68|#^U>4#+D4M&4a(5Qlb8ez

1muPxX|%*TiSNGo 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 Date: Tue, 12 Nov 2024 19:50:37 +0600 Subject: [PATCH 05/14] Add Update Version doc Signed-off-by: Neaj Morshad --- .../msops-update-ag-cluster.yaml | 13 + .../msops-update-standalone.yaml | 13 + .../update-version/mssql-ag-cluster.yaml | 44 + .../update-version/mssql-standalone.yaml | 32 + docs/guides/mssqlserver/README.md | 48 +- .../mssqlserver/reconfigure-tls/overview.md | 54 + .../reconfigure-tls/reconfigure-tls.md | 1006 +++++++++++++++++ .../mssqlserver/update-version/ag_cluster.md | 352 ++++++ .../mssqlserver/update-version/overview.md | 54 + .../mssqlserver/update-version/standalone.md | 306 +++++ 10 files changed, 1898 insertions(+), 24 deletions(-) create mode 100644 docs/examples/mssqlserver/update-version/msops-update-ag-cluster.yaml create mode 100644 docs/examples/mssqlserver/update-version/msops-update-standalone.yaml create mode 100644 docs/examples/mssqlserver/update-version/mssql-ag-cluster.yaml create mode 100644 docs/examples/mssqlserver/update-version/mssql-standalone.yaml create mode 100644 docs/guides/mssqlserver/reconfigure-tls/overview.md create mode 100644 docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md create mode 100644 docs/guides/mssqlserver/update-version/ag_cluster.md create mode 100644 docs/guides/mssqlserver/update-version/overview.md create mode 100644 docs/guides/mssqlserver/update-version/standalone.md diff --git a/docs/examples/mssqlserver/update-version/msops-update-ag-cluster.yaml b/docs/examples/mssqlserver/update-version/msops-update-ag-cluster.yaml new file mode 100644 index 0000000000..78a9ad9653 --- /dev/null +++ b/docs/examples/mssqlserver/update-version/msops-update-ag-cluster.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-update-ag-cluster + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: mssql-ag-cluster + updateVersion: + targetVersion: 2022-cu14 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/update-version/msops-update-standalone.yaml b/docs/examples/mssqlserver/update-version/msops-update-standalone.yaml new file mode 100644 index 0000000000..3f4c51368d --- /dev/null +++ b/docs/examples/mssqlserver/update-version/msops-update-standalone.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-update-standalone + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: mssql-standalone + updateVersion: + targetVersion: 2022-cu14 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/update-version/mssql-ag-cluster.yaml b/docs/examples/mssqlserver/update-version/mssql-ag-cluster.yaml new file mode 100644 index 0000000000..bad6f7bb95 --- /dev/null +++ b/docs/examples/mssqlserver/update-version/mssql-ag-cluster.yaml @@ -0,0 +1,44 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-ag-cluster + namespace: demo +spec: + version: "2022-cu12" + replicas: 3 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut diff --git a/docs/examples/mssqlserver/update-version/mssql-standalone.yaml b/docs/examples/mssqlserver/update-version/mssql-standalone.yaml new file mode 100644 index 0000000000..512bbeb784 --- /dev/null +++ b/docs/examples/mssqlserver/update-version/mssql-standalone.yaml @@ -0,0 +1,32 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + storageType: Durable + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/guides/mssqlserver/README.md b/docs/guides/mssqlserver/README.md index 6c5ab86ccc..ebd1502f8c 100644 --- a/docs/guides/mssqlserver/README.md +++ b/docs/guides/mssqlserver/README.md @@ -20,30 +20,30 @@ Microsoft SQL Server is one of the most popular relational database management s ## Supported Microsoft SQL Server Features -| Features | Availability | -|---------------------------------------------------------------------|:------------:| -| Standalone and Availability Group Cluster (HA configuration) | ✓ | -| Synchronous Replication | ✓ | -| Automatic Failover | ✓ | -| Custom Configuration | ✓ | -| Authentication & Authorization | ✓ | -| Externally manageable Auth Secret | ✓ | -| Instant and Scheduled Backup ([KubeStash](https://kubestash.com/)) | ✓ | -| Continuous Archiving using `wal-g` | ✓ | -| Initialization from WAL archive | ✓ | -| Initializing from Snapshot ([KubeStash](https://kubestash.com/)) | ✓ | -| Reconfigurable Health Checker | ✓ | -| Persistent volume | ✓ | -| Builtin Prometheus Discovery | ✓ | -| Using Prometheus operator | ✓ | -| Automated Version Update | ✓ | -| Automated Vertical Scaling, Volume Expansion | ✓ | -| Automated Horizontal Scaling | ✓ | -| Autoscaler for Compute and Storage Resources | ✓ | -| Reconfiguration | ✓ | -| TLS | ✓ | -| Grafana Dashboards | ✓ | -| Autoscaling (vertically) | ✓ | +| Features | Availability | +|--------------------------------------------------------------------|:------------:| +| Standalone and Availability Group Cluster (HA configuration) | ✓ | +| Synchronous Replication | ✓ | +| Automatic Failover | ✓ | +| Custom Configuration | ✓ | +| Authentication & Authorization | ✓ | +| Externally manageable Auth Secret | ✓ | +| Instant and Scheduled Backup ([KubeStash](https://kubestash.com/)) | ✓ | +| Continuous Archiving using `wal-g` | ✓ | +| Initialization from WAL archive | ✓ | +| Initializing from Snapshot ([KubeStash](https://kubestash.com/)) | ✓ | +| Reconfigurable Health Checker | ✓ | +| Persistent Volume | ✓ | +| Builtin Prometheus Discovery | ✓ | +| Using Prometheus operator | ✓ | +| Automated Version Update | ✓ | +| Automated Vertical Scaling, Volume Expansion | ✓ | +| Automated Horizontal Scaling | ✓ | +| Autoscaling Compute and Storage Resources | ✓ | +| Reconfiguration | ✓ | +| TLS | ✓ | +| Reconfigure TLS | ✓ | +| Grafana Dashboards | ✓ | ## Supported Microsoft SQL Server Versions diff --git a/docs/guides/mssqlserver/reconfigure-tls/overview.md b/docs/guides/mssqlserver/reconfigure-tls/overview.md new file mode 100644 index 0000000000..1c3b55d693 --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure-tls/overview.md @@ -0,0 +1,54 @@ +--- +title: Reconfiguring TLS of MSSQLServer Database +menu: + docs_{{ .version }}: + identifier: mg-reconfigure-tls-overview + name: Overview + parent: mg-reconfigure-tls + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfiguring TLS of MSSQLServer Database + +This guide will give an overview on how KubeDB Ops-manager operator reconfigures TLS configuration i.e. add TLS, remove TLS, update issuer/cluster issuer or Certificates and rotate the certificates of a `MSSQLServer` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + +## How Reconfiguring MSSQLServer TLS Configuration Process Works + +The following diagram shows how KubeDB Ops-manager operator reconfigures TLS of a `MSSQLServer` database. Open the image in a new tab to see the enlarged version. + +

+  Reconfiguring TLS process of MSSQLServer +
Fig: Reconfiguring TLS process of MSSQLServer
+
+ +The Reconfiguring MSSQLServer TLS process consists of the following steps: + +1. At first, a user creates a `MSSQLServer` Custom Resource Object (CRO). + +2. `KubeDB` Provisioner operator watches the `MSSQLServer` CRO. + +3. When the operator finds a `MSSQLServer` CR, it creates required number of `PetSets` and related necessary stuff like secrets, services, etc. + +4. Then, in order to reconfigure the TLS configuration of the `MSSQLServer` database the user creates a `MSSQLServerOpsRequest` CR with desired information. + +5. `KubeDB` Ops-manager operator watches the `MSSQLServerOpsRequest` CR. + +6. When it finds a `MSSQLServerOpsRequest` CR, it pauses the `MSSQLServer` object which is referred from the `MSSQLServerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `MSSQLServer` object during the reconfiguring TLS process. + +7. Then the `KubeDB` Ops-manager operator will add, remove, update or rotate TLS configuration based on the Ops Request yaml. + +8. Then the `KubeDB` Ops-manager operator will restart all the Pods of the database so that they restart with the new TLS configuration defined in the `MSSQLServerOpsRequest` CR. + +9. After the successful reconfiguring of the `MSSQLServer` TLS, the `KubeDB` Ops-manager operator resumes the `MSSQLServer` object so that the `KubeDB` Provisioner operator resumes its usual operations. + +In the next docs, we are going to show a step by step guide on reconfiguring TLS configuration of a MSSQLServer database using `MSSQLServerOpsRequest` CRD. \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md b/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md new file mode 100644 index 0000000000..dd0eb321d5 --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md @@ -0,0 +1,1006 @@ +--- +title: Reconfigure MSSQLServer TLS/SSL Encryption +menu: + docs_{{ .version }}: + identifier: mg-reconfigure-tls-rs + name: Reconfigure MSSQLServer TLS/SSL Encryption + parent: mg-reconfigure-tls + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure MSSQLServer TLS/SSL (Transport Encryption) + +KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing MSSQLServer database via a MSSQLServerOpsRequest. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Install [`cert-manger`](https://cert-manager.io/docs/installation/) v1.0.0 or later to your cluster to manage your SSL/TLS certificates. + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +> Note: YAML files used in this tutorial are stored in [docs/examples/mssqlserver](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/mssqlserver) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Add TLS to a MSSQLServer database + +Here, We are going to create a MSSQLServer database without TLS and then reconfigure the database to use TLS. + +### Deploy MSSQLServer without TLS + +In this section, we are going to deploy a MSSQLServer Replicaset database without TLS. In the next few sections we will reconfigure TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1 +kind: MSSQLServer +metadata: + name: mg-rs + namespace: demo +spec: + version: "4.4.26" + replicas: 3 + replicaSet: + name: rs0 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml +mssqlserver.kubedb.com/mg-rs created +``` + +Now, wait until `mg-replicaset` has status `Ready`. i.e, + +```bash +$ kubectl get mg -n demo +NAME VERSION STATUS AGE +mg-rs 4.4.26 Ready 10m + +$ kubectl dba describe mssqlserver mg-rs -n demo +Name: mg-rs +Namespace: demo +CreationTimestamp: Thu, 11 Mar 2021 13:25:05 +0600 +Labels: +Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"kubedb.com/v1","kind":"MSSQLServer","metadata":{"annotations":{},"name":"mg-rs","namespace":"demo"},"spec":{"replicaSet":{"name":"rs0"... +Replicas: 3 total +Status: Ready +StorageType: Durable +Volume: + StorageClass: standard + Capacity: 1Gi + Access Modes: RWO +Paused: false +Halted: false +Termination Policy: Delete + +PetSet: + Name: mg-rs + CreationTimestamp: Thu, 11 Mar 2021 13:25:05 +0600 + Labels: app.kubernetes.io/component=database + app.kubernetes.io/instance=mg-rs + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=mssqlservers.kubedb.com + Annotations: + Replicas: 824639275080 desired | 3 total + Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed + +Service: + Name: mg-rs + Labels: app.kubernetes.io/component=database + app.kubernetes.io/instance=mg-rs + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=mssqlservers.kubedb.com + Annotations: + Type: ClusterIP + IP: 10.96.70.27 + Port: primary 27017/TCP + TargetPort: db/TCP + Endpoints: 10.244.0.63:27017 + +Service: + Name: mg-rs-pods + Labels: app.kubernetes.io/component=database + app.kubernetes.io/instance=mg-rs + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=mssqlservers.kubedb.com + Annotations: + Type: ClusterIP + IP: None + Port: db 27017/TCP + TargetPort: db/TCP + Endpoints: 10.244.0.63:27017,10.244.0.65:27017,10.244.0.67:27017 + +Auth Secret: + Name: mg-rs-auth + Labels: app.kubernetes.io/component=database + app.kubernetes.io/instance=mg-rs + app.kubernetes.io/managed-by=kubedb.com + app.kubernetes.io/name=mssqlservers.kubedb.com + Annotations: + Type: Opaque + Data: + password: 16 bytes + username: 4 bytes + +AppBinding: + Metadata: + Annotations: + kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"kubedb.com/v1","kind":"MSSQLServer","metadata":{"annotations":{},"name":"mg-rs","namespace":"demo"},"spec":{"replicaSet":{"name":"rs0"},"replicas":3,"storage":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"1Gi"}},"storageClassName":"standard"},"version":"4.4.26"}} + + Creation Timestamp: 2021-03-11T07:26:44Z + Labels: + app.kubernetes.io/component: database + app.kubernetes.io/instance: mg-rs + app.kubernetes.io/managed-by: kubedb.com + app.kubernetes.io/name: mssqlservers.kubedb.com + Name: mg-rs + Namespace: demo + Spec: + Client Config: + Service: + Name: mg-rs + Port: 27017 + Scheme: mssqlserver + Parameters: + API Version: config.kubedb.com/v1alpha1 + Kind: MongoConfiguration + Replica Sets: + host-0: rs0/mg-rs-0.mg-rs-pods.demo.svc,mg-rs-1.mg-rs-pods.demo.svc,mg-rs-2.mg-rs-pods.demo.svc + Stash: + Addon: + Backup Task: + Name: mssqlserver-backup-4.4.6-v6 + Restore Task: + Name: mssqlserver-restore-4.4.6-v6 + Secret: + Name: mg-rs-auth + Type: kubedb.com/mssqlserver + Version: 4.4.26 + +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Successful 14m MSSQLServer operator Successfully created stats service + Normal Successful 14m MSSQLServer operator Successfully created Service + Normal Successful 14m MSSQLServer operator Successfully stats service + Normal Successful 14m MSSQLServer operator Successfully stats service + Normal Successful 13m MSSQLServer operator Successfully stats service + Normal Successful 13m MSSQLServer operator Successfully stats service + Normal Successful 13m MSSQLServer operator Successfully stats service + Normal Successful 13m MSSQLServer operator Successfully stats service + Normal Successful 13m MSSQLServer operator Successfully stats service + Normal Successful 12m MSSQLServer operator Successfully stats service + Normal Successful 12m MSSQLServer operator Successfully patched PetSet demo/mg-rs +``` + +Now, we can connect to this database through [mongo-shell](https://docs.mssqlserver.com/v4.2/mongo/) and verify that the TLS is disabled. + + +```bash +$ kubectl get secrets -n demo mg-rs-auth -o jsonpath='{.data.\username}' | base64 -d +root + +$ kubectl get secrets -n demo mg-rs-auth -o jsonpath='{.data.\password}' | base64 -d +U6(h_pYrekLZ2OOd + +$ kubectl exec -it mg-rs-0 -n demo -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' +rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) +{ + "sslMode" : "disabled", + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1615468344, 1), + "signature" : { + "hash" : BinData(0,"Xdclj9Y67WKZ/oTDGT/E1XzOY28="), + "keyId" : NumberLong("6938294279689207810") + } + }, + "operationTime" : Timestamp(1615468344, 1) +} +``` + +We can verify from the above output that TLS is disabled for this database. + +### Create Issuer/ ClusterIssuer + +Now, We are going to create an example `Issuer` that will be used to enable SSL/TLS in MSSQLServer. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. + +- Start off by generating a ca certificates using openssl. + +```bash +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=ca/O=kubedb" +Generating a RSA private key +................+++++ +........................+++++ +writing new private key to './ca.key' +----- +``` + +- Now we are going to create a ca-secret using the certificate files that we have just generated. + +```bash +$ kubectl create secret tls mongo-ca \ + --cert=ca.crt \ + --key=ca.key \ + --namespace=demo +secret/mongo-ca created +``` + +Now, Let's create an `Issuer` using the `mongo-ca` secret that we have just created. The `YAML` file looks like this: + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mg-issuer + namespace: demo +spec: + ca: + secretName: mongo-ca +``` + +Let's apply the `YAML` file: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml +issuer.cert-manager.io/mg-issuer created +``` + +### Create MSSQLServerOpsRequest + +In order to add TLS to the database, we have to create a `MSSQLServerOpsRequest` CRO with our created issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + issuerRef: + name: mg-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: client + subject: + organizations: + - mongo + organizationalUnits: + - client + readinessCriteria: + oplogMaxLagSeconds: 20 + objectsCountDiffPercentage: 10 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.issuerRef` specifies the issuer name, kind and api group. +- `spec.tls.certificates` specifies the certificates. You can learn more about this field from [here](/docs/guides/mssqlserver/concepts/mssqlserver.md#spectls). + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml +mssqlserveropsrequest.ops.kubedb.com/mops-add-tls created +``` + +#### Verify TLS Enabled Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +mops-add-tls ReconfigureTLS Successful 91s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo mops-add-tls +Name: mops-add-tls +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-11T13:32:18Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:databaseRef: + .: + f:name: + f:tls: + .: + f:certificates: + f:issuerRef: + .: + f:apiGroup: + f:kind: + f:name: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-11T13:32:18Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-11T13:32:19Z + Resource Version: 488264 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-add-tls + UID: 0024ec16-0d43-4686-a2d7-1cdeb96e41a5 +Spec: + Database Ref: + Name: mg-rs + Tls: + Certificates: + Alias: client + Subject: + Organizational Units: + client + Organizations: + mongo + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mg-issuer + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2021-03-11T13:32:19Z + Message: MSSQLServer ops request is reconfiguring TLS + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2021-03-11T13:32:25Z + Message: Successfully Updated PetSets + Observed Generation: 1 + Reason: TLSAdded + Status: True + Type: TLSAdded + Last Transition Time: 2021-03-11T13:34:25Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2021-03-11T13:34:25Z + Message: Successfully Reconfigured TLS + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 2m10s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-rs + Normal PauseDatabase 2m10s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-rs + Normal TLSAdded 2m10s KubeDB Ops-manager operator Successfully Updated PetSets + Normal RestartReplicaSet 10s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes + Normal ResumeDatabase 10s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-rs + Normal ResumeDatabase 10s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-rs + Normal Successful 10s KubeDB Ops-manager operator Successfully Reconfigured TLS +``` + +Now, Let's exec into a database primary node and find out the username to connect in a mongo shell, + +```bash +$ kubectl exec -it mg-rs-2 -n demo bash +root@mgo-rs-tls-2:/$ ls /var/run/mssqlserver/tls +ca.crt client.pem mongo.pem +root@mgo-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -subject -nameopt RFC2253 -noout +subject=CN=root,OU=client,O=mongo +``` + +Now, we can connect using `CN=root,OU=client,O=mongo` as root to connect to the mongo shell of the master pod, + +```bash +root@mgo-rs-tls-2:/$ mongo --tls --tlsCAFile /var/run/mssqlserver/tls/ca.crt --tlsCertificateKeyFile /var/run/mssqlserver/tls/client.pem admin --host localhost --authenticationMechanism MONGODB-X509 --authenticationDatabase='$external' -u "CN=root,OU=client,O=mongo" --quiet +rs0:PRIMARY> +``` + +We are connected to the mongo shell. Let's run some command to verify the sslMode and the user, + +```bash +rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) +{ + "sslMode" : "requireSSL", + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1615472249, 1), + "signature" : { + "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), + "keyId" : NumberLong(0) + } + }, + "operationTime" : Timestamp(1615472249, 1) +} +``` + +We can see from the above output that, `sslMode` is set to `requireSSL`. So, database TLS is enabled successfully to this database. + +## Rotate Certificate + +Now we are going to rotate the certificate of this database. First let's check the current expiration date of the certificate. + +```bash +$ kubectl exec -it mg-rs-2 -n demo bash +root@mg-rs-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Jun 9 13:32:20 2021 GMT +``` + +So, the certificate will expire on this time `Jun 9 13:32:20 2021 GMT`. + +### Create MSSQLServerOpsRequest + +Now we are going to increase it using a MSSQLServerOpsRequest. Below is the yaml of the ops request that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-rotate + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + rotateCertificates: true +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this database. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml +mssqlserveropsrequest.ops.kubedb.com/mops-rotate created +``` + +#### Verify Certificate Rotated Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +mops-rotate ReconfigureTLS Successful 112s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo mops-rotate +Name: mops-rotate +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-11T16:17:55Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:databaseRef: + .: + f:name: + f:tls: + .: + f:rotateCertificates: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-11T16:17:55Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-11T16:17:55Z + Resource Version: 521643 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-rotate + UID: 6d96ead2-a868-47d8-85fb-77eecc9a96b4 +Spec: + Database Ref: + Name: mg-rs + Tls: + Rotate Certificates: true + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2021-03-11T16:17:55Z + Message: MSSQLServer ops request is reconfiguring TLS + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2021-03-11T16:17:55Z + Message: Successfully Added Issuing Condition in Certificates + Observed Generation: 1 + Reason: IssuingConditionUpdated + Status: True + Type: IssuingConditionUpdated + Last Transition Time: 2021-03-11T16:18:00Z + Message: Successfully Issued New Certificates + Observed Generation: 1 + Reason: CertificateIssuingSuccessful + Status: True + Type: CertificateIssuingSuccessful + Last Transition Time: 2021-03-11T16:19:45Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2021-03-11T16:19:45Z + Message: Successfully Reconfigured TLS + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal CertificateIssuingSuccessful 2m10s KubeDB Ops-manager operator Successfully Issued New Certificates + Normal RestartReplicaSet 25s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes + Normal Successful 25s KubeDB Ops-manager operator Successfully Reconfigured TLS +``` + +Now, let's check the expiration date of the certificate. + +```bash +$ kubectl exec -it mg-rs-2 -n demo bash +root@mg-rs-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Jun 9 16:17:55 2021 GMT +``` + +As we can see from the above output, the certificate has been rotated successfully. + +## Change Issuer/ClusterIssuer + +Now, we are going to change the issuer of this database. + +- Let's create a new ca certificate and key using a different subject `CN=ca-update,O=kubedb-updated`. + +```bash +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=ca-updated/O=kubedb-updated" +Generating a RSA private key +..............................................................+++++ +......................................................................................+++++ +writing new private key to './ca.key' +----- +``` + +- Now we are going to create a new ca-secret using the certificate files that we have just generated. + +```bash +$ kubectl create secret tls mongo-new-ca \ + --cert=ca.crt \ + --key=ca.key \ + --namespace=demo +secret/mongo-new-ca created +``` + +Now, Let's create a new `Issuer` using the `mongo-new-ca` secret that we have just created. The `YAML` file looks like this: + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mg-new-issuer + namespace: demo +spec: + ca: + secretName: mongo-new-ca +``` + +Let's apply the `YAML` file: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml +issuer.cert-manager.io/mg-new-issuer created +``` + +### Create MSSQLServerOpsRequest + +In order to use the new issuer to issue new certificates, we have to create a `MSSQLServerOpsRequest` CRO with the newly created issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-change-issuer + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + issuerRef: + name: mg-new-issuer + kind: Issuer + apiGroup: "cert-manager.io" +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.issuerRef` specifies the issuer name, kind and api group. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml +mssqlserveropsrequest.ops.kubedb.com/mops-change-issuer created +``` + +#### Verify Issuer is changed successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +mops-change-issuer ReconfigureTLS Successful 105s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo mops-change-issuer +Name: mops-change-issuer +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-11T16:27:47Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:databaseRef: + .: + f:name: + f:tls: + .: + f:issuerRef: + .: + f:apiGroup: + f:kind: + f:name: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-11T16:27:47Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-11T16:27:47Z + Resource Version: 523903 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-change-issuer + UID: cdfe8a7d-52ef-466c-a5dd-97e74ad598ca +Spec: + Database Ref: + Name: mg-rs + Tls: + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mg-new-issuer + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2021-03-11T16:27:47Z + Message: MSSQLServer ops request is reconfiguring TLS + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2021-03-11T16:27:52Z + Message: Successfully Issued New Certificates + Observed Generation: 1 + Reason: CertificateIssuingSuccessful + Status: True + Type: CertificateIssuingSuccessful + Last Transition Time: 2021-03-11T16:29:37Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2021-03-11T16:29:37Z + Message: Successfully Reconfigured TLS + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal CertificateIssuingSuccessful 2m27s KubeDB Ops-manager operator Successfully Issued New Certificates + Normal RestartReplicaSet 42s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes + Normal Successful 42s KubeDB Ops-manager operator Successfully Reconfigured TLS +``` + +Now, Let's exec into a database node and find out the ca subject to see if it matches the one we have provided. + +```bash +$ kubectl exec -it mg-rs-2 -n demo bash +root@mgo-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout +subject=O=kubedb-updated,CN=ca-updated +``` + +We can see from the above output that, the subject name matches the subject name of the new ca certificate that we have created. So, the issuer is changed successfully. + +## Remove TLS from the Database + +Now, we are going to remove TLS from this database using a MSSQLServerOpsRequest. + +### Create MSSQLServerOpsRequest + +Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-remove + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + remove: true +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.remove` specifies that we want to remove tls from this database. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml +mssqlserveropsrequest.ops.kubedb.com/mops-remove created +``` + +#### Verify TLS Removed Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +mops-remove ReconfigureTLS Successful 105s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo mops-remove +Name: mops-remove +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2021-03-11T16:35:32Z + Generation: 1 + Managed Fields: + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:metadata: + f:annotations: + .: + f:kubectl.kubernetes.io/last-applied-configuration: + f:spec: + .: + f:databaseRef: + .: + f:name: + f:tls: + .: + f:remove: + f:type: + Manager: kubectl-client-side-apply + Operation: Update + Time: 2021-03-11T16:35:32Z + API Version: ops.kubedb.com/v1alpha1 + Fields Type: FieldsV1 + fieldsV1: + f:status: + .: + f:conditions: + f:observedGeneration: + f:phase: + Manager: kubedb-enterprise + Operation: Update + Time: 2021-03-11T16:35:32Z + Resource Version: 525550 + Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-remove + UID: 99184cc4-1595-4f0f-b8eb-b65c5d0e86a6 +Spec: + Database Ref: + Name: mg-rs + Tls: + Remove: true + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2021-03-11T16:35:32Z + Message: MSSQLServer ops request is reconfiguring TLS + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2021-03-11T16:35:37Z + Message: Successfully Updated PetSets + Observed Generation: 1 + Reason: TLSRemoved + Status: True + Type: TLSRemoved + Last Transition Time: 2021-03-11T16:37:07Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2021-03-11T16:37:07Z + Message: Successfully Reconfigured TLS + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 2m5s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-rs + Normal PauseDatabase 2m5s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-rs + Normal TLSRemoved 2m5s KubeDB Ops-manager operator Successfully Updated PetSets + Normal RestartReplicaSet 35s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes + Normal ResumeDatabase 35s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-rs + Normal ResumeDatabase 35s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-rs + Normal Successful 35s KubeDB Ops-manager operator Successfully Reconfigured TLS +``` + +Now, Let's exec into the database primary node and find out that TLS is disabled or not. + +```bash +$ kubectl exec -it -n demo mg-rs-1 -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' +rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) +{ + "sslMode" : "disabled", + "ok" : 1, + "$clusterTime" : { + "clusterTime" : Timestamp(1615480817, 1), + "signature" : { + "hash" : BinData(0,"CWJngDTQqDhKXyx7WMFJqqUfvhY="), + "keyId" : NumberLong("6938294279689207810") + } + }, + "operationTime" : Timestamp(1615480817, 1) +} +``` + +So, we can see from the above that, output that tls is disabled successfully. + +## Cleaning up + +To cleanup the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete mssqlserver -n demo mg-rs +kubectl delete issuer -n demo mg-issuer mg-new-issuer +kubectl delete mssqlserveropsrequest mops-add-tls mops-remove mops-rotate mops-change-issuer +kubectl delete ns demo +``` + +## Next Steps + +- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mssqlserver.md). +- Initialize [MSSQLServer with Script](/docs/guides/mssqlserver/initialization/using-script.md). +- Monitor your MSSQLServer database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/mssqlserver/monitoring/using-prometheus-operator.md). +- Monitor your MSSQLServer database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/mssqlserver/monitoring/using-builtin-prometheus.md). +- Use [private Docker registry](/docs/guides/mssqlserver/private-registry/using-private-registry.md) to deploy MSSQLServer with KubeDB. +- Use [kubedb cli](/docs/guides/mssqlserver/cli/cli.md) to manage databases like kubectl for Kubernetes. +- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mongodb.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/mssqlserver/update-version/ag_cluster.md b/docs/guides/mssqlserver/update-version/ag_cluster.md new file mode 100644 index 0000000000..25fa4408e9 --- /dev/null +++ b/docs/guides/mssqlserver/update-version/ag_cluster.md @@ -0,0 +1,352 @@ +--- +title: Updating MSSQLServer Availability Group +menu: + docs_{{ .version }}: + identifier: ms-updating-ag-cluster + name: Availability Group (HA Cluster) + parent: mssql-updating + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Update version of MSSQLServer Availability Group + +This guide will show you how to use `KubeDB` Ops-manager operator to update the version of `MSSQLServer` Availability Group Cluster. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [Availability Group Cluster](/docs/guides/mssqlserver/clustering/ag_cluster.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + - [Updating Overview](/docs/guides/mssqlserver/update-version/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver/update-version) directory of [kubedb/docs](https://github.com/kube/docs) repository. + +## Prepare MSSQLServer Availability Group Database + +First, an issuer needs to be created, even if TLS is not enabled for SQL Server. The issuer will be used to configure the TLS-enabled Wal-G proxy server, which is required for the SQL Server backup and restore operations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/ag-cluster/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + +Now, we are going to deploy a `MSSQLServer` availability group with version `2022-cu12`. + +### Deploy MSSQLServer AG Cluster + +In this section, we are going to deploy a MSSQLServer availability group cluster. Then, in the next section we will update the version of the database using `MSSQLServerOpsRequest` CR. + +Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-ag-cluster + namespace: demo +spec: + version: "2022-cu12" + replicas: 3 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/update-version/mssql-ag-cluster.yaml +mssqlserver.kubedb.com/mssql-ag-cluster created +``` + +Now, wait until `mssql-ag-cluster` created has status `Ready`. i.e, + +```bash +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +mssql-ag-cluster 2022-cu12 Ready 4m +``` + +We are now ready to apply the `MSSQLServerOpsRequest` CR to update this database. + +### Update MSSQLServer Version + +Here, we are going to update `MSSQLServer` ag cluster from `2022-cu12` to `2022-cu14`. + +#### Create MSSQLServerOpsRequest: + +In order to update the version of the mssql server ag cluster database, we have to create a `MSSQLServerOpsRequest` CR with your desired version that is supported by `KubeDB`. +Below is the YAML of the `MSSQLServerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-update-ag-cluster + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: mssql-ag-cluster + updateVersion: + targetVersion: 2022-cu14 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing operation on `mssql-ag-cluster` MSSQLServer database. +- `spec.type` specifies that we are going to perform `UpdateVersion` on our database. +- `spec.updateVersion.targetVersion` specifies the expected version of the database `2022-cu14`. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#spectimeout) on the respective sections to understand the `timeout` & `apply` fields. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/update-version/msops-update-ag-cluster .yaml +mssqlserveropsrequest.ops.kubedb.com/msops-update-ag-cluster created +``` + +#### Verify MSSQLServer version updated successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the image of `MSSQLServer` object and related `PetSets` and `Pods`. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +msops-update-ag-cluster UpdateVersion Successful 2m33s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to update the database version. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-update-ag-cluster +Name: msops-update-ag-cluster +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-12T13:38:04Z + Generation: 1 + Resource Version: 333751 + UID: f4977424-0ddc-40bc-a3b7-bc69f5ac6e82 +Spec: + Apply: IfReady + Database Ref: + Name: mssql-ag-cluster + Timeout: 5m + Type: UpdateVersion + Update Version: + Target Version: 2022-cu14 +Status: + Conditions: + Last Transition Time: 2024-11-12T13:38:05Z + Message: MSSQLServer ops-request has started to update version + Observed Generation: 1 + Reason: UpdateVersion + Status: True + Type: UpdateVersion + Last Transition Time: 2024-11-12T13:38:28Z + Message: successfully reconciled the MSSQLServer with updated version + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-12T13:38:33Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-12T13:38:33Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-12T13:39:08Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-0 + Last Transition Time: 2024-11-12T13:39:13Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-12T13:39:13Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-12T13:39:48Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-1 + Last Transition Time: 2024-11-12T13:39:53Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-12T13:39:53Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-12T13:40:28Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-2 + Last Transition Time: 2024-11-12T13:40:33Z + Message: Successfully Restarted MSSQLServer pods + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2024-11-12T13:40:33Z + Message: Successfully updated MSSQLServer + Observed Generation: 1 + Reason: UpdateDatabase + Status: True + Type: UpdateDatabase + Last Transition Time: 2024-11-12T13:40:33Z + Message: Successfully updated MSSQLServer version + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 7m49s KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-update-ag-cluster + Normal Starting 7m49s KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/mssql-ag-cluster + Normal Successful 7m49s KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/mssql-ag-cluster for MSSQLServerOpsRequest: msops-update-ag-cluster + Normal UpdatePetSets 7m26s KubeDB Ops-manager Operator successfully reconciled the MSSQLServer with updated version + Warning get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 7m21s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Warning evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 7m21s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Warning check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-0 7m16s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-0 + Warning check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 6m46s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Warning get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 6m41s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Warning evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 6m41s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Warning check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-1 6m36s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-1 + Warning check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 6m6s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Warning get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 6m1s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Warning evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 6m1s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Warning check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-2 5m56s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssql-ag-cluster-2 + Warning check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 5m26s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Normal RestartPods 5m21s KubeDB Ops-manager Operator Successfully Restarted MSSQLServer pods + Normal Starting 5m21s KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/mssql-ag-cluster + Normal Successful 5m21s KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/mssql-ag-cluster for MSSQLServerOpsRequest: msops-update-ag-cluster +``` + +Now, we are going to verify whether the `MSSQLServer` and the related `PetSets` and their `Pods` have the new version image. Let's check, + +```bash +$ kubectl get ms -n demo mssql-ag-cluster -o=jsonpath='{.spec.version}{"\n"}' +2022-cu14 + +$ kubectl get petset -n demo mssql-ag-cluster -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}' +mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04@sha256:c1aa8afe9b06eab64c9774a4802dcd032205d1be785b1fd51e1c0151e7586b74 + +$ kubectl get pods -n demo mssql-ag-cluster-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}' +mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04 +``` + +You can see from above, our `MSSQLServer` ag database cluster has been updated with the new version. So, the updateVersion process is successfully completed. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete ms -n demo mssql-ag-cluster +kubectl delete msops -n demo msops-update-ag-cluster +kubectl delete issuer -n demo mssqlserver-ca-issuer +kubectl delete secret -n demo mssqlserver-ca +kubectl delete ns demo +``` \ No newline at end of file diff --git a/docs/guides/mssqlserver/update-version/overview.md b/docs/guides/mssqlserver/update-version/overview.md new file mode 100644 index 0000000000..db2847c9b1 --- /dev/null +++ b/docs/guides/mssqlserver/update-version/overview.md @@ -0,0 +1,54 @@ +--- +title: Updating MSSQLServer Overview +menu: + docs_{{ .version }}: + identifier: ms-updating-overview + name: Overview + parent: mssql-updating + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Updating MSSQLServer version Overview + +This guide will give you an overview on how KubeDB Ops-manager operator update the version of `MSSQLServer` database. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + +## How update version Process Works + +The following diagram shows how KubeDB Ops-manager operator update the version of `MSSQLServer`. Open the image in a new tab to see the enlarged version. + +
+  updating Process of MSSQLServer +
Fig: Updating Process of MSSQLServer
+
+ +The updating process consists of the following steps: + +1. At first, a user creates a `MSSQLServer` Custom Resource (CR). + +2. `KubeDB` Provisioner operator watches the `MSSQLServer` CR. + +3. When the operator finds a `MSSQLServer` CR, it creates `PetSets` and related necessary resources like secrets, services, etc. + +4. Then, in order to update the version of the `MSSQLServer` the user creates a `MSSQLServerOpsRequest` CR with the desired version. + +5. `KubeDB` Ops-manager operator watches the `MSSQLServerOpsRequest` CR. + +6. When it finds a `MSSQLServerOpsRequest` CR, it halts the `MSSQLServer` object which is referred from the `MSSQLServerOpsRequest`. So, the `KubeDB` Provisioner operator doesn't perform any operations on the `MSSQLServer` object during the updating process. + +7. By looking at the target version from `MSSQLServerOpsRequest` CR, `KubeDB` Ops-manager operator updates the images of the `PetSet`. + +8. After successfully updating the `PetSet` and their `Pods` images, the `KubeDB` Ops-manager operator updates the image of the `MSSQLServer` object to reflect the updated state of the database. + +9. After successfully updating of `MSSQLServer` object, the `KubeDB` Ops-manager operator resumes the `MSSQLServer` object so that the `KubeDB` Provisioner operator can resume its usual operations. + +In the next doc, we are going to show a step-by-step guide on updating of a MSSQLServer using UpdateVersion operation. \ No newline at end of file diff --git a/docs/guides/mssqlserver/update-version/standalone.md b/docs/guides/mssqlserver/update-version/standalone.md new file mode 100644 index 0000000000..3fa059fd55 --- /dev/null +++ b/docs/guides/mssqlserver/update-version/standalone.md @@ -0,0 +1,306 @@ +--- +title: Updating MSSQLServer Standalone +menu: + docs_{{ .version }}: + identifier: ms-updating-standalone + name: Standalone + parent: mssql-updating + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Update Version of MSSQLServer Standalone + +This guide will show you how to use `KubeDB` Ops-manager operator to update the version of `MSSQLServer` standalone. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + - [Updating Overview](/docs/guides/mssqlserver/update-version/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver/update-version) directory of [kubedb/docs](https://github.com/kube/docs) repository. + +### Prepare MSSQLServer Standalone Database + +Now, we are going to deploy a `MSSQLServer` standalone database with version `2022-cu12`. + +### Deploy MSSQLServer Standalone + +In this section, we are going to deploy a MSSQLServer standalone database. Then, in the next section we will update the version of the database using `MSSQLServerOpsRequest` CR. + +At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + + +### Create MSSSQLServer + +Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + storageType: Durable + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/update-version/mssql-standalone.yaml +mssqlserver.kubedb.com/mssql-standalone created +``` + +Now, wait until `mssql-standalone` created has status `Ready`. i.e, + +```bash +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +mssql-standalone 2022-cu12 Ready 3m8s +``` + +We are now ready to apply the `MSSQLServerOpsRequest` CR to update this database. + +### Update MSSQLServer Version + +Here, we are going to update `MSSQLServer` standalone from `2022-cu12` to `2022-cu14`. + +#### Create MSSQLServerOpsRequest: + +In order to update the standalone database, we have to create a `MSSQLServerOpsRequest` CR with our desired version that is supported by `KubeDB`. Below is the YAML of the `MSSQLServerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-update-standalone + namespace: demo +spec: + type: UpdateVersion + databaseRef: + name: mssql-standalone + updateVersion: + targetVersion: 2022-cu14 + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing operation on `mssql-standalone` database. +- `spec.type` specifies that we are going to perform `UpdateVersion` on our database. +- `spec.updateVersion.targetVersion` specifies the expected version of the database `2022-cu14`. +- Have a look [here](/docs/guides/mssqlserver/concepts/opsrequest.md#spectimeout) on the respective sections to understand the `timeout` & `apply` fields. + + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/update-version/msops-update-standalone.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-update-standalone created +``` + +#### Verify MSSQLServer version updated successfully : + +If everything goes well, `KubeDB` Ops-manager operator will update the image of `MSSQLServer` object and related `PetSets` and `Pods`. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ watch kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +msops-update-standalone UpdateVersion Successful 2m28s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to update the database. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-update-standalone +Name: msops-update-standalone +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-12T12:46:07Z + Generation: 1 + Resource Version: 328223 + UID: 7038611f-8ebe-4fb9-8f79-1d73e9669445 +Spec: + Apply: IfReady + Database Ref: + Name: mssql-standalone + Timeout: 5m + Type: UpdateVersion + Update Version: + Target Version: 2022-cu14 +Status: + Conditions: + Last Transition Time: 2024-11-12T12:46:07Z + Message: MSSQLServer ops-request has started to update version + Observed Generation: 1 + Reason: UpdateVersion + Status: True + Type: UpdateVersion + Last Transition Time: 2024-11-12T12:46:16Z + Message: successfully reconciled the MSSQLServer with updated version + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-12T12:46:21Z + Message: get pod; ConditionStatus:True; PodName:mssql-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-standalone-0 + Last Transition Time: 2024-11-12T12:46:21Z + Message: evict pod; ConditionStatus:True; PodName:mssql-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-standalone-0 + Last Transition Time: 2024-11-12T12:48:16Z + Message: check pod running; ConditionStatus:True; PodName:mssql-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-standalone-0 + Last Transition Time: 2024-11-12T12:48:21Z + Message: Successfully Restarted MSSQLServer pods + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2024-11-12T12:48:21Z + Message: Successfully updated MSSQLServer + Observed Generation: 1 + Reason: UpdateDatabase + Status: True + Type: UpdateDatabase + Last Transition Time: 2024-11-12T12:48:21Z + Message: Successfully updated MSSQLServer version + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 2m42s KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-update-standalone + Normal Starting 2m42s KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/mssql-standalone + Normal Successful 2m42s KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/mssql-standalone for MSSQLServerOpsRequest: msops-update-standalone + Normal UpdatePetSets 2m33s KubeDB Ops-manager Operator successfully reconciled the MSSQLServer with updated version + Warning get pod; ConditionStatus:True; PodName:mssql-standalone-0 2m28s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssql-standalone-0 + Warning evict pod; ConditionStatus:True; PodName:mssql-standalone-0 2m28s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssql-standalone-0 + Warning check pod running; ConditionStatus:False; PodName:mssql-standalone-0 2m23s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssql-standalone-0 + Warning check pod running; ConditionStatus:True; PodName:mssql-standalone-0 33s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssql-standalone-0 + Normal RestartPods 28s KubeDB Ops-manager Operator Successfully Restarted MSSQLServer pods + Normal Starting 28s KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/mssql-standalone + Normal Successful 28s KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/mssql-standalone for MSSQLServerOpsRequest: msops-update-standalone +``` + +Now, we are going to verify whether the `MSSQLServer` and the related `PetSets` their `Pods` have the new version image. Let's check, + +```bash +$ kubectl get ms -n demo mssql-standalone -o=jsonpath='{.spec.version}{"\n"}' +2022-cu14 + +$ kubectl get petset -n demo mssql-standalone -o=jsonpath='{.spec.template.spec.containers[0].image}{"\n"}' +mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04@sha256:c1aa8afe9b06eab64c9774a4802dcd032205d1be785b1fd51e1c0151e7586b74 + +$ kubectl get pods -n demo mssql-standalone-0 -o=jsonpath='{.spec.containers[0].image}{"\n"}' +mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04 +``` + +You can see from above, our `MSSQLServer` standalone database has been updated with the new version. So, the update process is successfully completed. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete ms -n demo mssql-standalone +kubectl delete msops -n demo msops-update-standalone +kubectl delete issuer -n demo mssqlserver-ca-issuer +kubectl delete secret -n demo mssqlserver-ca +kubectl delete ns demo +``` \ No newline at end of file From cd7626a5a8757a49c7eef38099d92800bb0b9d40 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Wed, 13 Nov 2024 11:37:04 +0600 Subject: [PATCH 06/14] Add volume expansion standalone Signed-off-by: Neaj Morshad --- .../mssqlserver/reconfigure-tls/issuer.yaml | 8 + .../reconfigure-tls/mg-replicaset.yaml | 17 + .../reconfigure-tls/mops-add-tls.yaml | 21 + .../reconfigure-tls/mops-change-issuer.yaml | 14 + .../reconfigure-tls/mops-remove.yaml | 11 + .../reconfigure-tls/mops-rotate.yaml | 11 + .../reconfigure-tls/new-issuer.yaml | 8 + .../volume-expansion/mops-volume-exp-std.yaml | 12 + .../volume-expansion/mssql-standalone.yaml | 38 ++ .../{volume-expansion.md => ag_cluster.md} | 14 +- .../volume-expansion/standalone.md | 381 ++++++++++++++++++ 11 files changed, 528 insertions(+), 7 deletions(-) create mode 100644 docs/examples/mssqlserver/reconfigure-tls/issuer.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml create mode 100644 docs/examples/mssqlserver/volume-expansion/mops-volume-exp-std.yaml create mode 100644 docs/examples/mssqlserver/volume-expansion/mssql-standalone.yaml rename docs/guides/mssqlserver/volume-expansion/{volume-expansion.md => ag_cluster.md} (97%) create mode 100644 docs/guides/mssqlserver/volume-expansion/standalone.md diff --git a/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml new file mode 100644 index 0000000000..b001fb7268 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mg-issuer + namespace: demo +spec: + ca: + secretName: mongo-ca diff --git a/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml b/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml new file mode 100644 index 0000000000..b271b8a5f2 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml @@ -0,0 +1,17 @@ +apiVersion: kubedb.com/v1 +kind: MongoDB +metadata: + name: mg-rs + namespace: demo +spec: + version: "4.4.26" + replicas: 3 + replicaSet: + name: rs0 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml b/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml new file mode 100644 index 0000000000..25ed1b09e4 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml @@ -0,0 +1,21 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mops-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + issuerRef: + name: mg-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: client + subject: + organizations: + - mongo + organizationalUnits: + - client diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml new file mode 100644 index 0000000000..3543909617 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mops-change-issuer + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + issuerRef: + name: mg-new-issuer + kind: Issuer + apiGroup: "cert-manager.io" diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml b/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml new file mode 100644 index 0000000000..06245506d9 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mops-remove + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + remove: true diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml b/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml new file mode 100644 index 0000000000..7530796118 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mops-rotate + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mg-rs + tls: + rotateCertificates: true diff --git a/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml new file mode 100644 index 0000000000..066cbce511 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml @@ -0,0 +1,8 @@ +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mg-new-issuer + namespace: demo +spec: + ca: + secretName: mongo-new-ca diff --git a/docs/examples/mssqlserver/volume-expansion/mops-volume-exp-std.yaml b/docs/examples/mssqlserver/volume-expansion/mops-volume-exp-std.yaml new file mode 100644 index 0000000000..c1112e2709 --- /dev/null +++ b/docs/examples/mssqlserver/volume-expansion/mops-volume-exp-std.yaml @@ -0,0 +1,12 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-volume-exp-std + namespace: demo +spec: + type: VolumeExpansion + databaseRef: + name: mssql-standalone + volumeExpansion: + mode: "Offline" # Online + mssqlserver: 2Gi diff --git a/docs/examples/mssqlserver/volume-expansion/mssql-standalone.yaml b/docs/examples/mssqlserver/volume-expansion/mssql-standalone.yaml new file mode 100644 index 0000000000..b9392192c8 --- /dev/null +++ b/docs/examples/mssqlserver/volume-expansion/mssql-standalone.yaml @@ -0,0 +1,38 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + storageType: Durable + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/guides/mssqlserver/volume-expansion/volume-expansion.md b/docs/guides/mssqlserver/volume-expansion/ag_cluster.md similarity index 97% rename from docs/guides/mssqlserver/volume-expansion/volume-expansion.md rename to docs/guides/mssqlserver/volume-expansion/ag_cluster.md index 4bf7d105e2..fc8ba8a0fe 100644 --- a/docs/guides/mssqlserver/volume-expansion/volume-expansion.md +++ b/docs/guides/mssqlserver/volume-expansion/ag_cluster.md @@ -1,11 +1,11 @@ --- -title: MSSQLServer Volume Expansion +title: Availability Group (HA Cluster) Volume Expansion menu: docs_{{ .version }}: - identifier: mssqlserver-volume-expansion-guide - name: MSSQLServer Volume Expansion + identifier: volume-expansion-guide-ag-cluster + name: Availability Group (HA Cluster) parent: ms-volume-expansion - weight: 20 + weight: 30 menu_name: docs_{{ .version }} section_menu_id: guides --- @@ -14,7 +14,7 @@ section_menu_id: guides # MSSQLServer Volume Expansion -This guide will show you how to use `KubeDB` Ops-manager operator to expand the volume of a MSSQLServer. +This guide will show you how to use `KubeDB` Ops-manager operator to expand the volume of a SQL Server Availability Group Cluster. ## Before You Begin @@ -38,11 +38,11 @@ $ kubectl create ns demo namespace/demo created ``` -## Expand Volume of MSSQLServer +## Expand Volume of MSSQLServer Availability Group Cluster Here, we are going to deploy a `MSSQLServer` cluster using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to expand its volume. The process of expanding MSSQLServer `standalone` is same as MSSQLServer Availability Group cluster. -### Prepare MSSQLServer +### Prepare MSSQLServer Availability Group Cluster At first verify that your cluster has a storage class, that supports volume expansion. Let's check, diff --git a/docs/guides/mssqlserver/volume-expansion/standalone.md b/docs/guides/mssqlserver/volume-expansion/standalone.md new file mode 100644 index 0000000000..8cc2596a8a --- /dev/null +++ b/docs/guides/mssqlserver/volume-expansion/standalone.md @@ -0,0 +1,381 @@ +--- +title: Standalone Volume Expansion +menu: + docs_{{ .version }}: + identifier: volume-expansion-guide-standalone + name: Standalone + parent: ms-volume-expansion + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# MSSQLServer Volume Expansion + +This guide will show you how to use `KubeDB` Ops-manager operator to expand the volume of a SQL Server Standalone. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You must have a `StorageClass` that supports volume expansion. + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + - [Volume Expansion Overview](/docs/guides/mssqlserver/volume-expansion/overview.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +## Expand Volume of MSSQLServer + +Here, we are going to deploy a `MSSQLServer` standalone using a supported version by `KubeDB` operator. Then we are going to apply `MSSQLServerOpsRequest` to expand its volume. The process of expanding MSSQLServer `standalone` is same as MSSQLServer Availability Group cluster. + +### Prepare MSSQLServer Standalone + +At first verify that your cluster has a storage class, that supports volume expansion. Let's check, + +```bash +$ kubectl get storageclass +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +local-path (default) rancher.io/local-path Delete WaitForFirstConsumer false 2d +longhorn (default) driver.longhorn.io Delete Immediate true 3m25s +longhorn-static driver.longhorn.io Delete Immediate true 3m19s +``` + +We can see from the output that `longhorn (default)` storage class has `ALLOWVOLUMEEXPANSION` field as true. So, this storage class supports volume expansion. We will use this storage class. + + +Now, we are going to deploy a `MSSQLServer` in `AvailabilityGroup` Mode with version `2022-cu12`. + +### Deploy MSSQLServer Standalone + +First, an issuer needs to be created, even if TLS is not enabled for SQL Server. The issuer will be used to configure the TLS-enabled Wal-G proxy server, which is required for the SQL Server backup and restore operations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + +In this section, we are going to deploy a MSSQLServer Standalone with 1GB volume. Then, in the next section we will expand its volume to 2GB using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssql-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + storageType: Durable + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" + storage: + storageClassName: "longhorn" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/volume-expansion/mssql-standalone.yaml +mssqlserver.kubedb.com/mssql-standalone created +``` + +Now, wait until `mssql-standalone` has status `Ready`. i.e, + +```bash +$ kubectl get ms -n demo mssql-standalone +NAME VERSION STATUS AGE +mssql-standalone 2022-cu12 Ready 5m +``` + +Let's check volume size from petset, and from the persistent volume, + +```bash +$ kubectl get petset -n demo mssql-standalone -o json | jq '.spec.volumeClaimTemplates[].spec.resources.requests.storage' +"1Gi" + +$ kubectl get pv -n demo +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE +pvc-7e7ed996-b682-4d84-8450-4c06fe92b11f 1Gi RWO Delete Bound demo/data-mssql-standalone-0 longhorn 5m29s +``` + +You can see the petset has 1GB storage, and the capacity of all the persistent volumes are also 1GB. + +We are now ready to apply the `MSSQLServerOpsRequest` CR to expand the volume of this database. + +### Volume Expansion + +Here, we are going to expand the volume of the MSSQLServer Standalone. + +#### Create MSSQLServerOpsRequest + +In order to expand the volume of the database, we have to create a `MSSQLServerOpsRequest` CR with our desired volume size. Below is the YAML of the `MSSQLServerOpsRequest` CR that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: mops-volume-exp-std + namespace: demo +spec: + type: VolumeExpansion + databaseRef: + name: mssql-standalone + volumeExpansion: + mode: "Offline" # Online + mssqlserver: 2Gi +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing volume expansion operation on `mssql-standalone` database. +- `spec.type` specifies that we are performing `VolumeExpansion` on our database. +- `spec.volumeExpansion.mssqlserver` specifies the desired volume size. +- `spec.volumeExpansion.mode` specifies the desired volume expansion mode (`Online` or `Offline`). Storageclass `longhorn` supports `Offline` volume expansion. + +> **Note:** If the Storageclass you are using support `Online` Volume Expansion, Try Online volume expansion by using `spec.volumeExpansion.mode:"Online"`. + +During `Online` VolumeExpansion KubeDB expands volume without deleting the pods, it directly updates the underlying PVC. And for Offline volume expansion, the database is paused. The Pods are deleted and PVC is updated. Then the database Pods are recreated with updated PVC. + + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/example/mssqlserver/volume-expansion/mops-volume-exp-std.yaml +mssqlserveropsrequest.ops.kubedb.com/mops-volume-exp-std created +``` + +#### Verify MSSQLServer volume expanded successfully + +If everything goes well, `KubeDB` Ops-manager operator will update the volume size of `MSSQLServer` object and related `PetSet` and `Persistent Volumes`. + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CR, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +mops-volume-exp-std VolumeExpansion Successful 9m +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed to expand the volume of the database. + +```bash +$ kubectl describe msops -n demo mops-volume-exp-std +Name: mops-volume-exp-std +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-13T05:13:02Z + Generation: 1 + Resource Version: 2235347 + UID: e9d3733d-f472-406f-ade4-c92eea771d61 +Spec: + Apply: IfReady + Database Ref: + Name: mssql-standalone + Type: VolumeExpansion + Volume Expansion: + Mode: Offline + Mssqlserver: 2Gi +Status: + Conditions: + Last Transition Time: 2024-11-13T05:13:02Z + Message: MSSQLServer ops-request has started to expand volume of mssqlserver nodes. + Observed Generation: 1 + Reason: VolumeExpansion + Status: True + Type: VolumeExpansion + Last Transition Time: 2024-11-13T05:13:40Z + Message: get petset; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPetset + Last Transition Time: 2024-11-13T05:13:40Z + Message: delete petset; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: DeletePetset + Last Transition Time: 2024-11-13T05:13:50Z + Message: successfully deleted the petSets with orphan propagation policy + Observed Generation: 1 + Reason: OrphanPetSetPods + Status: True + Type: OrphanPetSetPods + Last Transition Time: 2024-11-13T05:19:00Z + Message: get pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPod + Last Transition Time: 2024-11-13T05:13:55Z + Message: patch ops request; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: PatchOpsRequest + Last Transition Time: 2024-11-13T05:13:55Z + Message: delete pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: DeletePod + Last Transition Time: 2024-11-13T05:19:00Z + Message: get pvc; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPvc + Last Transition Time: 2024-11-13T05:19:00Z + Message: patch pvc; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: PatchPvc + Last Transition Time: 2024-11-13T05:19:20Z + Message: compare storage; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CompareStorage + Last Transition Time: 2024-11-13T05:19:20Z + Message: create pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CreatePod + Last Transition Time: 2024-11-13T05:19:25Z + Message: running mssql server; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: RunningMssqlServer + Last Transition Time: 2024-11-13T05:19:45Z + Message: successfully updated node PVC sizes + Observed Generation: 1 + Reason: UpdateNodePVCs + Status: True + Type: UpdateNodePVCs + Last Transition Time: 2024-11-13T05:19:50Z + Message: successfully reconciled the MSSQLServer resources + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-13T05:19:55Z + Message: get pet set; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetPetSet + Last Transition Time: 2024-11-13T05:19:55Z + Message: PetSet is recreated + Observed Generation: 1 + Reason: ReadyPetSets + Status: True + Type: ReadyPetSets + Last Transition Time: 2024-11-13T05:19:55Z + Message: Successfully completed volumeExpansion for MSSQLServer + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +``` + +Now, we are going to verify from the `Petset`, and the `Persistent Volumes` whether the volume of the database has expanded to meet the desired state, Let's check, + +```bash +$ kubectl get petset -n demo mssql-standalone -o json | jq '.spec.volumeClaimTemplates[].spec.resources.requests.storage' +"2Gi" + +$ kubectl get pv -n demo +NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE +pvc-7e7ed996-b682-4d84-8450-4c06fe92b11f 2Gi RWO Delete Bound demo/data-mssql-standalone-0 longhorn 26m +``` + +The above output verifies that we have successfully expanded the volume of the MSSQLServer Standalone database. + +## Cleaning Up + +To clean up the Kubernetes resources created by this tutorial, run: + + +```bash +$ kubectl patch -n demo ms/mssql-standalone -p '{"spec":{"deletionPolicy":"WipeOut"}}' --type="merge" +mssqlserver.kubedb.com/mssql-standalone patched + +$ kubectl delete -n demo mssqlserver mssql-standalone +mssqlserver.kubedb.com "mssql-standalone" deleted + +$ kubectl delete -n demo mssqlserveropsrequest mops-volume-exp-std +mssqlserveropsrequest.ops.kubedb.com "mops-volume-exp-std" deleted + +kubectl delete issuer -n demo mssqlserver-ca-issuer +kubectl delete secret -n demo mssqlserver-ca +kubectl delete ns demo +``` + +## Next Steps + +- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mssqlserver.md). +- [Backup and Restore](/docs/guides/mssqlserver/backup/overview/index.md) MSSQLServer databases using KubeStash. \ No newline at end of file From 30b230fe0e2a0a5aa1ccd0f855edab76f568276a Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Thu, 14 Nov 2024 17:20:52 +0600 Subject: [PATCH 07/14] reconfigure tls overview Signed-off-by: Neaj Morshad --- docs/guides/mssqlserver/reconfigure-tls/overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/guides/mssqlserver/reconfigure-tls/overview.md b/docs/guides/mssqlserver/reconfigure-tls/overview.md index 1c3b55d693..fed48c1742 100644 --- a/docs/guides/mssqlserver/reconfigure-tls/overview.md +++ b/docs/guides/mssqlserver/reconfigure-tls/overview.md @@ -2,9 +2,9 @@ title: Reconfiguring TLS of MSSQLServer Database menu: docs_{{ .version }}: - identifier: mg-reconfigure-tls-overview + identifier: ms-reconfigure-tls-overview name: Overview - parent: mg-reconfigure-tls + parent: ms-reconfigure-tls weight: 10 menu_name: docs_{{ .version }} section_menu_id: guides @@ -27,7 +27,7 @@ This guide will give an overview on how KubeDB Ops-manager operator reconfigures The following diagram shows how KubeDB Ops-manager operator reconfigures TLS of a `MSSQLServer` database. Open the image in a new tab to see the enlarged version.
-  Reconfiguring TLS process of MSSQLServer +  Reconfiguring TLS process of MSSQLServer
Fig: Reconfiguring TLS process of MSSQLServer
@@ -51,4 +51,4 @@ The Reconfiguring MSSQLServer TLS process consists of the following steps: 9. After the successful reconfiguring of the `MSSQLServer` TLS, the `KubeDB` Ops-manager operator resumes the `MSSQLServer` object so that the `KubeDB` Provisioner operator resumes its usual operations. -In the next docs, we are going to show a step by step guide on reconfiguring TLS configuration of a MSSQLServer database using `MSSQLServerOpsRequest` CRD. \ No newline at end of file +In the next docs, we are going to show a step-by-step guide on reconfiguring TLS configuration of a MSSQLServer database using `MSSQLServerOpsRequest` CRD. \ No newline at end of file From b0cd92177b396e0f12c001c108205a4c1bbdf9b2 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Thu, 14 Nov 2024 19:35:03 +0600 Subject: [PATCH 08/14] reconfigure tls guide wip tls added Signed-off-by: Neaj Morshad --- .../reconfigure-tls/ms-standalone.yaml | 32 + .../msops-reconfigure-ag-apply.yaml | 16 + .../reconfigure-tls/msops-reconfigure-ag.yaml | 14 + .../msops-reconfigure-standalone-apply.yaml | 16 + .../msops-reconfigure-standalone.yaml | 14 + .../mssqlserver-ag-cluster.yaml | 40 + .../reconfigure-tls/reconfigure-tls.md | 695 +++++++++--------- 7 files changed, 492 insertions(+), 335 deletions(-) create mode 100644 docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml diff --git a/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml b/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml new file mode 100644 index 0000000000..e9ab5d95b7 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml @@ -0,0 +1,32 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: ms-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml new file mode 100644 index 0000000000..b93d450d54 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml @@ -0,0 +1,16 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-ag-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mssqlserver-ag-cluster + configuration: + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml new file mode 100644 index 0000000000..86d2b8283d --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-ag + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: mssqlserver-ag-cluster + configuration: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml new file mode 100644 index 0000000000..0199028a1b --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml @@ -0,0 +1,16 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone-apply + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + applyConfig: + mssql.conf: |- + [memory] + memorylimitmb = 3072 + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml new file mode 100644 index 0000000000..5c0f52531a --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-reconfigure-standalone + namespace: demo +spec: + type: Reconfigure + databaseRef: + name: ms-standalone + configuration: + configSecret: + name: new-custom-config + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml b/docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml new file mode 100644 index 0000000000..8407bb6fcf --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml @@ -0,0 +1,40 @@ +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssqlserver-ag-cluster + namespace: demo +spec: + version: "2022-cu12" + configSecret: + name: ms-custom-config + replicas: 3 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Developer + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md b/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md index dd0eb321d5..dfcf1ad384 100644 --- a/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md +++ b/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md @@ -2,27 +2,27 @@ title: Reconfigure MSSQLServer TLS/SSL Encryption menu: docs_{{ .version }}: - identifier: mg-reconfigure-tls-rs - name: Reconfigure MSSQLServer TLS/SSL Encryption - parent: mg-reconfigure-tls - weight: 10 + identifier: ms-reconfigure-tls-standalone + name: Standalone + parent: ms-reconfigure-tls + weight: 20 menu_name: docs_{{ .version }} section_menu_id: guides --- > New to KubeDB? Please start [here](/docs/README.md). -# Reconfigure MSSQLServer TLS/SSL (Transport Encryption) +# Reconfigure Standalone MSSQLServer TLS/SSL (Transport Encryption) KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing MSSQLServer database via a MSSQLServerOpsRequest. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. ## Before You Begin -- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). -- Install [`cert-manger`](https://cert-manager.io/docs/installation/) v1.0.0 or later to your cluster to manage your SSL/TLS certificates. +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. -- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). - To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. @@ -31,276 +31,308 @@ KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL cer namespace/demo created ``` -> Note: YAML files used in this tutorial are stored in [docs/examples/mssqlserver](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/mssqlserver) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). +> Note: YAML files used in this tutorial are stored in [docs/examples/mssqlserver](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). ## Add TLS to a MSSQLServer database Here, We are going to create a MSSQLServer database without TLS and then reconfigure the database to use TLS. +At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + ### Deploy MSSQLServer without TLS -In this section, we are going to deploy a MSSQLServer Replicaset database without TLS. In the next few sections we will reconfigure TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, +In this section, we are going to deploy a MSSQLServer Standalone database without TLS. In the next few sections we will reconfigure TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, ```yaml -apiVersion: kubedb.com/v1 +apiVersion: kubedb.com/v1alpha2 kind: MSSQLServer metadata: - name: mg-rs + name: ms-standalone namespace: demo spec: - version: "4.4.26" - replicas: 3 - replicaSet: - name: rs0 + version: "2022-cu12" + replicas: 1 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + storageType: Durable storage: storageClassName: "standard" accessModes: - - ReadWriteOnce + - ReadWriteOnce resources: requests: storage: 1Gi + deletionPolicy: WipeOut ``` Let's create the `MSSQLServer` CR we have shown above, ```bash -$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml -mssqlserver.kubedb.com/mg-rs created +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml +mssqlserver.kubedb.com/ms-standalone created ``` -Now, wait until `mg-replicaset` has status `Ready`. i.e, +Now, wait until `ms-standalone` has status `Ready`. i.e, ```bash -$ kubectl get mg -n demo -NAME VERSION STATUS AGE -mg-rs 4.4.26 Ready 10m - -$ kubectl dba describe mssqlserver mg-rs -n demo -Name: mg-rs -Namespace: demo -CreationTimestamp: Thu, 11 Mar 2021 13:25:05 +0600 -Labels: -Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"kubedb.com/v1","kind":"MSSQLServer","metadata":{"annotations":{},"name":"mg-rs","namespace":"demo"},"spec":{"replicaSet":{"name":"rs0"... -Replicas: 3 total -Status: Ready -StorageType: Durable -Volume: - StorageClass: standard - Capacity: 1Gi - Access Modes: RWO -Paused: false -Halted: false -Termination Policy: Delete - -PetSet: - Name: mg-rs - CreationTimestamp: Thu, 11 Mar 2021 13:25:05 +0600 - Labels: app.kubernetes.io/component=database - app.kubernetes.io/instance=mg-rs - app.kubernetes.io/managed-by=kubedb.com - app.kubernetes.io/name=mssqlservers.kubedb.com - Annotations: - Replicas: 824639275080 desired | 3 total - Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed - -Service: - Name: mg-rs - Labels: app.kubernetes.io/component=database - app.kubernetes.io/instance=mg-rs - app.kubernetes.io/managed-by=kubedb.com - app.kubernetes.io/name=mssqlservers.kubedb.com - Annotations: - Type: ClusterIP - IP: 10.96.70.27 - Port: primary 27017/TCP - TargetPort: db/TCP - Endpoints: 10.244.0.63:27017 - -Service: - Name: mg-rs-pods - Labels: app.kubernetes.io/component=database - app.kubernetes.io/instance=mg-rs - app.kubernetes.io/managed-by=kubedb.com - app.kubernetes.io/name=mssqlservers.kubedb.com - Annotations: - Type: ClusterIP - IP: None - Port: db 27017/TCP - TargetPort: db/TCP - Endpoints: 10.244.0.63:27017,10.244.0.65:27017,10.244.0.67:27017 - -Auth Secret: - Name: mg-rs-auth - Labels: app.kubernetes.io/component=database - app.kubernetes.io/instance=mg-rs - app.kubernetes.io/managed-by=kubedb.com - app.kubernetes.io/name=mssqlservers.kubedb.com - Annotations: - Type: Opaque - Data: - password: 16 bytes - username: 4 bytes - -AppBinding: - Metadata: - Annotations: - kubectl.kubernetes.io/last-applied-configuration: {"apiVersion":"kubedb.com/v1","kind":"MSSQLServer","metadata":{"annotations":{},"name":"mg-rs","namespace":"demo"},"spec":{"replicaSet":{"name":"rs0"},"replicas":3,"storage":{"accessModes":["ReadWriteOnce"],"resources":{"requests":{"storage":"1Gi"}},"storageClassName":"standard"},"version":"4.4.26"}} - - Creation Timestamp: 2021-03-11T07:26:44Z - Labels: - app.kubernetes.io/component: database - app.kubernetes.io/instance: mg-rs - app.kubernetes.io/managed-by: kubedb.com - app.kubernetes.io/name: mssqlservers.kubedb.com - Name: mg-rs - Namespace: demo - Spec: - Client Config: - Service: - Name: mg-rs - Port: 27017 - Scheme: mssqlserver - Parameters: - API Version: config.kubedb.com/v1alpha1 - Kind: MongoConfiguration - Replica Sets: - host-0: rs0/mg-rs-0.mg-rs-pods.demo.svc,mg-rs-1.mg-rs-pods.demo.svc,mg-rs-2.mg-rs-pods.demo.svc - Stash: - Addon: - Backup Task: - Name: mssqlserver-backup-4.4.6-v6 - Restore Task: - Name: mssqlserver-restore-4.4.6-v6 - Secret: - Name: mg-rs-auth - Type: kubedb.com/mssqlserver - Version: 4.4.26 +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +ms-standalone 2022-cu12 Ready 4m3s +$ kubectl describe ms -n demo ms-standalone +Name: ms-standalone +Namespace: demo +Labels: +Annotations: +API Version: kubedb.com/v1alpha2 +Kind: MSSQLServer +Metadata: + Creation Timestamp: 2024-11-14T12:45:36Z + Finalizers: + kubedb.com + Generation: 2 + Resource Version: 438804 + UID: 83ebe191-3754-41af-8d86-ed211bf9c31c +Spec: + Auth Secret: + Name: ms-standalone-auth + Deletion Policy: WipeOut + Health Checker: + Failure Threshold: 1 + Period Seconds: 10 + Timeout Seconds: 10 + Pod Template: + Controller: + Metadata: + Spec: + Containers: + Env: + Name: ACCEPT_EULA + Value: Y + Name: MSSQL_PID + Value: Evaluation + Name: mssql + Resources: + Limits: + Memory: 4Gi + Requests: + Cpu: 500m + Memory: 4Gi + Security Context: + Allow Privilege Escalation: false + Capabilities: + Add: + NET_BIND_SERVICE + Drop: + ALL + Run As Group: 10001 + Run As Non Root: true + Run As User: 10001 + Seccomp Profile: + Type: RuntimeDefault + Init Containers: + Name: mssql-init + Resources: + Limits: + Memory: 512Mi + Requests: + Cpu: 200m + Memory: 512Mi + Security Context: + Allow Privilege Escalation: false + Capabilities: + Drop: + ALL + Run As Group: 10001 + Run As Non Root: true + Run As User: 10001 + Seccomp Profile: + Type: RuntimeDefault + Pod Placement Policy: + Name: default + Security Context: + Fs Group: 10001 + Replicas: 1 + Storage: + Access Modes: + ReadWriteOnce + Resources: + Requests: + Storage: 1Gi + Storage Class Name: standard + Storage Type: Durable + Tls: + Certificates: + Alias: server + Secret Name: ms-standalone-server-cert + Subject: + Organizational Units: + server + Organizations: + kubedb + Alias: client + Secret Name: ms-standalone-client-cert + Subject: + Organizational Units: + client + Organizations: + kubedb + Client TLS: false + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mssqlserver-ca-issuer + Version: 2022-cu12 +Status: + Conditions: + Last Transition Time: 2024-11-14T12:45:36Z + Message: The KubeDB operator has started the provisioning of MSSQLServer: demo/ms-standalone + Observed Generation: 1 + Reason: DatabaseProvisioningStartedSuccessfully + Status: True + Type: ProvisioningStarted + Last Transition Time: 2024-11-14T12:46:36Z + Message: All replicas are ready for MSSQLServer demo/ms-standalone + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: ReplicaReady + Last Transition Time: 2024-11-14T12:46:46Z + Message: database demo/ms-standalone is accepting connection + Observed Generation: 2 + Reason: AcceptingConnection + Status: True + Type: AcceptingConnection + Last Transition Time: 2024-11-14T12:46:46Z + Message: database demo/ms-standalone is ready + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: Ready + Last Transition Time: 2024-11-14T12:47:06Z + Message: The MSSQLServer: demo/ms-standalone is successfully provisioned. + Observed Generation: 2 + Reason: DatabaseSuccessfullyProvisioned + Status: True + Type: Provisioned + Phase: Ready Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal Successful 14m MSSQLServer operator Successfully created stats service - Normal Successful 14m MSSQLServer operator Successfully created Service - Normal Successful 14m MSSQLServer operator Successfully stats service - Normal Successful 14m MSSQLServer operator Successfully stats service - Normal Successful 13m MSSQLServer operator Successfully stats service - Normal Successful 13m MSSQLServer operator Successfully stats service - Normal Successful 13m MSSQLServer operator Successfully stats service - Normal Successful 13m MSSQLServer operator Successfully stats service - Normal Successful 13m MSSQLServer operator Successfully stats service - Normal Successful 12m MSSQLServer operator Successfully stats service - Normal Successful 12m MSSQLServer operator Successfully patched PetSet demo/mg-rs -``` - -Now, we can connect to this database through [mongo-shell](https://docs.mssqlserver.com/v4.2/mongo/) and verify that the TLS is disabled. - + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer server certificates + Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer client certificates -```bash -$ kubectl get secrets -n demo mg-rs-auth -o jsonpath='{.data.\username}' | base64 -d -root - -$ kubectl get secrets -n demo mg-rs-auth -o jsonpath='{.data.\password}' | base64 -d -U6(h_pYrekLZ2OOd - -$ kubectl exec -it mg-rs-0 -n demo -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' -rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) -{ - "sslMode" : "disabled", - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1615468344, 1), - "signature" : { - "hash" : BinData(0,"Xdclj9Y67WKZ/oTDGT/E1XzOY28="), - "keyId" : NumberLong("6938294279689207810") - } - }, - "operationTime" : Timestamp(1615468344, 1) -} ``` -We can verify from the above output that TLS is disabled for this database. +Now, connect to this database by exec into a pod and verify the TLS is disabled. -### Create Issuer/ ClusterIssuer +> when we connect using the sqlcmd tool, the -N option is available with [s|m|o] parameters, where 's' stands for strict, 'm' for mandatory, and 'o' for optional. The default setting is mandatory. -Now, We are going to create an example `Issuer` that will be used to enable SSL/TLS in MSSQLServer. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. - -- Start off by generating a ca certificates using openssl. ```bash -$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=ca/O=kubedb" -Generating a RSA private key -................+++++ -........................+++++ -writing new private key to './ca.key' ------ -``` +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\username}' | base64 -d +sa -- Now we are going to create a ca-secret using the certificate files that we have just generated. +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\password}' | base64 -d +b1HLv9EV4CaSalX6 -```bash -$ kubectl create secret tls mongo-ca \ - --cert=ca.crt \ - --key=ca.key \ - --namespace=demo -secret/mongo-ca created -``` +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate]. +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Client unable to establish connection. -Now, Let's create an `Issuer` using the `mongo-ca` secret that we have just created. The `YAML` file looks like this: -```yaml -apiVersion: cert-manager.io/v1 -kind: Issuer -metadata: - name: mg-issuer - namespace: demo -spec: - ca: - secretName: mongo-ca +So Now, we have to connect with -C [Trust Server Certificate] +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N -C +1> ``` -Let's apply the `YAML` file: - -```bash -$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml -issuer.cert-manager.io/mg-issuer created -``` +We can verify from the above output that TLS is disabled for this database, `mssql.conf` file has no tls configuration. +Now we will enable tls configuration using MSSQLServerOpsRequest ### Create MSSQLServerOpsRequest -In order to add TLS to the database, we have to create a `MSSQLServerOpsRequest` CRO with our created issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, +In order to add TLS to the database, we have to create a `MSSQLServerOpsRequest` CRO with our issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, ```yaml apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-add-tls + name: msops-add-tls namespace: demo spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: issuerRef: - name: mg-issuer + name: mssqlserver-ca-issuer kind: Issuer apiGroup: "cert-manager.io" certificates: - alias: client subject: organizations: - - mongo + - mssqlserver organizationalUnits: - client - readinessCriteria: - oplogMaxLagSeconds: 20 - objectsCountDiffPercentage: 10 + clientTLS: true timeout: 5m apply: IfReady ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.issuerRef` specifies the issuer name, kind and api group. - `spec.tls.certificates` specifies the certificates. You can learn more about this field from [here](/docs/guides/mssqlserver/concepts/mssqlserver.md#spectls). @@ -308,8 +340,8 @@ Here, Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml -mssqlserveropsrequest.ops.kubedb.com/mops-add-tls created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-add-tls created ``` #### Verify TLS Enabled Successfully @@ -317,67 +349,33 @@ mssqlserveropsrequest.ops.kubedb.com/mops-add-tls created Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, ```bash -$ kubectl get mssqlserveropsrequest -n demo -Every 2.0s: kubectl get mssqlserveropsrequest -n demo -NAME TYPE STATUS AGE -mops-add-tls ReconfigureTLS Successful 91s +$ watch kubectl get msops -n demo +Every 2.0s: kubectl get msops -n demo + +NAME TYPE STATUS AGE +msops-add-tls ReconfigureTLS Successful 115s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo mops-add-tls -Name: mops-add-tls +$ kubectl describe mssqlserveropsrequest -n demo msops-add-tls +Name: msops-add-tls Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-11T13:32:18Z + Creation Timestamp: 2024-11-15T11:48:03Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:databaseRef: - .: - f:name: - f:tls: - .: - f:certificates: - f:issuerRef: - .: - f:apiGroup: - f:kind: - f:name: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-11T13:32:18Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-11T13:32:19Z - Resource Version: 488264 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-add-tls - UID: 0024ec16-0d43-4686-a2d7-1cdeb96e41a5 + Resource Version: 491162 + UID: 007ad725-0a3f-4290-8814-d85592cfc247 Spec: + Apply: IfReady Database Ref: - Name: mg-rs + Name: ms-standalone + Timeout: 5m Tls: Certificates: Alias: client @@ -385,96 +383,123 @@ Spec: Organizational Units: client Organizations: - mongo + mssqlserver + Client TLS: true Issuer Ref: API Group: cert-manager.io Kind: Issuer - Name: mg-issuer + Name: mssqlserver-ca-issuer Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2021-03-11T13:32:19Z - Message: MSSQLServer ops request is reconfiguring TLS + Last Transition Time: 2024-11-15T11:48:03Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2021-03-11T13:32:25Z - Message: Successfully Updated PetSets + Last Transition Time: 2024-11-15T11:48:06Z + Message: Successfully paused database Observed Generation: 1 - Reason: TLSAdded + Reason: DatabasePauseSucceeded Status: True - Type: TLSAdded - Last Transition Time: 2021-03-11T13:34:25Z - Message: Successfully Restarted ReplicaSet nodes + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-15T11:48:16Z + Message: Successfully synced all certificates Observed Generation: 1 - Reason: RestartReplicaSet + Reason: CertificateSynced Status: True - Type: RestartReplicaSet - Last Transition Time: 2021-03-11T13:34:25Z - Message: Successfully Reconfigured TLS + Type: CertificateSynced + Last Transition Time: 2024-11-15T11:48:11Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-15T11:48:11Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-15T11:48:11Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-15T11:48:21Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-15T11:49:06Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-15T11:48:26Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-15T11:48:26Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-15T11:49:01Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-15T11:49:07Z + Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal PauseDatabase 2m10s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-rs - Normal PauseDatabase 2m10s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-rs - Normal TLSAdded 2m10s KubeDB Ops-manager operator Successfully Updated PetSets - Normal RestartReplicaSet 10s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes - Normal ResumeDatabase 10s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-rs - Normal ResumeDatabase 10s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-rs - Normal Successful 10s KubeDB Ops-manager operator Successfully Reconfigured TLS ``` -Now, Let's exec into a database primary node and find out the username to connect in a mongo shell, +Now, Let's exec into a database node -```bash -$ kubectl exec -it mg-rs-2 -n demo bash -root@mgo-rs-tls-2:/$ ls /var/run/mssqlserver/tls -ca.crt client.pem mongo.pem -root@mgo-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -subject -nameopt RFC2253 -noout -subject=CN=root,OU=client,O=mongo -``` -Now, we can connect using `CN=root,OU=client,O=mongo` as root to connect to the mongo shell of the master pod, ```bash -root@mgo-rs-tls-2:/$ mongo --tls --tlsCAFile /var/run/mssqlserver/tls/ca.crt --tlsCertificateKeyFile /var/run/mssqlserver/tls/client.pem admin --host localhost --authenticationMechanism MONGODB-X509 --authenticationDatabase='$external' -u "CN=root,OU=client,O=mongo" --quiet -rs0:PRIMARY> +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ ls /var/opt/mssql/tls +ca.crt client.crt client.key server.crt server.key +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -subject -nameopt RFC2253 -noout +subject=CN=mssql,OU=client,O=mssqlserver +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[network] +forceencryption = 1 +tlscert = /var/opt/mssql/tls/server.crt +tlskey = /var/opt/mssql/tls/server.key +tlsprotocols = 1.2,1.1,1.0 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P l2mGQRMETAS96QRb -N +1> ``` -We are connected to the mongo shell. Let's run some command to verify the sslMode and the user, +We can verify from the above output that TLS is enabled for this database, `mssql.conf` file has tls configurations. So, TLS is enabled successfully to this database. -```bash -rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) -{ - "sslMode" : "requireSSL", - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1615472249, 1), - "signature" : { - "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), - "keyId" : NumberLong(0) - } - }, - "operationTime" : Timestamp(1615472249, 1) -} -``` -We can see from the above output that, `sslMode` is set to `requireSSL`. So, database TLS is enabled successfully to this database. + + + +start from here. .... + ## Rotate Certificate Now we are going to rotate the certificate of this database. First let's check the current expiration date of the certificate. ```bash -$ kubectl exec -it mg-rs-2 -n demo bash -root@mg-rs-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout +$ kubectl exec -it ms-standalone-2 -n demo bash +root@ms-standalone-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout notAfter=Jun 9 13:32:20 2021 GMT ``` @@ -493,14 +518,14 @@ metadata: spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: rotateCertificates: true ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this database. @@ -571,7 +596,7 @@ Metadata: UID: 6d96ead2-a868-47d8-85fb-77eecc9a96b4 Spec: Database Ref: - Name: mg-rs + Name: ms-standalone Tls: Rotate Certificates: true Type: ReconfigureTLS @@ -620,8 +645,8 @@ Events: Now, let's check the expiration date of the certificate. ```bash -$ kubectl exec -it mg-rs-2 -n demo bash -root@mg-rs-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout +$ kubectl exec -it ms-standalone-2 -n demo bash +root@ms-standalone-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout notAfter=Jun 9 16:17:55 2021 GMT ``` @@ -658,7 +683,7 @@ Now, Let's create a new `Issuer` using the `mongo-new-ca` secret that we have ju apiVersion: cert-manager.io/v1 kind: Issuer metadata: - name: mg-new-issuer + name: ms-new-issuer namespace: demo spec: ca: @@ -669,7 +694,7 @@ Let's apply the `YAML` file: ```bash $ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml -issuer.cert-manager.io/mg-new-issuer created +issuer.cert-manager.io/ms-new-issuer created ``` ### Create MSSQLServerOpsRequest @@ -685,17 +710,17 @@ metadata: spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: issuerRef: - name: mg-new-issuer + name: ms-new-issuer kind: Issuer apiGroup: "cert-manager.io" ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.issuerRef` specifies the issuer name, kind and api group. @@ -770,12 +795,12 @@ Metadata: UID: cdfe8a7d-52ef-466c-a5dd-97e74ad598ca Spec: Database Ref: - Name: mg-rs + Name: ms-standalone Tls: Issuer Ref: API Group: cert-manager.io Kind: Issuer - Name: mg-new-issuer + Name: ms-new-issuer Type: ReconfigureTLS Status: Conditions: @@ -816,8 +841,8 @@ Events: Now, Let's exec into a database node and find out the ca subject to see if it matches the one we have provided. ```bash -$ kubectl exec -it mg-rs-2 -n demo bash -root@mgo-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout +$ kubectl exec -it ms-standalone-2 -n demo bash +root@ms o-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout subject=O=kubedb-updated,CN=ca-updated ``` @@ -840,14 +865,14 @@ metadata: spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: remove: true ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mg-rs` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.remove` specifies that we want to remove tls from this database. @@ -918,7 +943,7 @@ Metadata: UID: 99184cc4-1595-4f0f-b8eb-b65c5d0e86a6 Spec: Database Ref: - Name: mg-rs + Name: ms-standalone Tls: Remove: true Type: ReconfigureTLS @@ -953,19 +978,19 @@ Status: Events: Type Reason Age From Message ---- ------ ---- ---- ------- - Normal PauseDatabase 2m5s KubeDB Ops-manager operator Pausing MSSQLServer demo/mg-rs - Normal PauseDatabase 2m5s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/mg-rs + Normal PauseDatabase 2m5s KubeDB Ops-manager operator Pausing MSSQLServer demo/ms-standalone + Normal PauseDatabase 2m5s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/ms-standalone Normal TLSRemoved 2m5s KubeDB Ops-manager operator Successfully Updated PetSets Normal RestartReplicaSet 35s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes - Normal ResumeDatabase 35s KubeDB Ops-manager operator Resuming MSSQLServer demo/mg-rs - Normal ResumeDatabase 35s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/mg-rs + Normal ResumeDatabase 35s KubeDB Ops-manager operator Resuming MSSQLServer demo/ms-standalone + Normal ResumeDatabase 35s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/ms-standalone Normal Successful 35s KubeDB Ops-manager operator Successfully Reconfigured TLS ``` Now, Let's exec into the database primary node and find out that TLS is disabled or not. ```bash -$ kubectl exec -it -n demo mg-rs-1 -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' +$ kubectl exec -it -n demo ms-standalone-1 -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) { "sslMode" : "disabled", @@ -988,9 +1013,9 @@ So, we can see from the above that, output that tls is disabled successfully. To cleanup the Kubernetes resources created by this tutorial, run: ```bash -kubectl delete mssqlserver -n demo mg-rs -kubectl delete issuer -n demo mg-issuer mg-new-issuer -kubectl delete mssqlserveropsrequest mops-add-tls mops-remove mops-rotate mops-change-issuer +kubectl delete mssqlserver -n demo ms-standalone +kubectl delete issuer -n demo ms-issuer ms-new-issuer +kubectl delete mssqlserveropsrequest msops-add-tls mops-remove mops-rotate mops-change-issuer kubectl delete ns demo ``` From 599e261f4527858f8949889551947945dfa76b41 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Fri, 15 Nov 2024 18:39:16 +0600 Subject: [PATCH 09/14] Finish reconfigure tls for standalone Signed-off-by: Neaj Morshad --- .../mssqlserver/reconfigure-tls/issuer.yaml | 4 +- .../reconfigure-tls/mops-change-issuer.yaml | 14 - .../{mops-add-tls.yaml => msops-add-tls.yaml} | 13 +- .../reconfigure-tls/msops-change-issuer.yaml | 14 + .../{mops-remove.yaml => msops-remove.yaml} | 8 +- .../{mops-rotate.yaml => msops-rotate.yaml} | 8 +- .../reconfigure-tls/new-issuer.yaml | 4 +- .../{reconfigure-tls.md => ag_cluster.md} | 193 ++-- .../mssqlserver/reconfigure-tls/standalone.md | 1008 +++++++++++++++++ 9 files changed, 1139 insertions(+), 127 deletions(-) delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml rename docs/examples/mssqlserver/reconfigure-tls/{mops-add-tls.yaml => msops-add-tls.yaml} (63%) create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-change-issuer.yaml rename docs/examples/mssqlserver/reconfigure-tls/{mops-remove.yaml => msops-remove.yaml} (56%) rename docs/examples/mssqlserver/reconfigure-tls/{mops-rotate.yaml => msops-rotate.yaml} (58%) rename docs/guides/mssqlserver/reconfigure-tls/{reconfigure-tls.md => ag_cluster.md} (87%) create mode 100644 docs/guides/mssqlserver/reconfigure-tls/standalone.md diff --git a/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml index b001fb7268..7a00e196d9 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml @@ -1,8 +1,8 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: - name: mg-issuer + name: mssqlserver-ca-issuer namespace: demo spec: ca: - secretName: mongo-ca + secretName: mssqlserver-ca \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml deleted file mode 100644 index 3543909617..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: ops.kubedb.com/v1alpha1 -kind: MongoDBOpsRequest -metadata: - name: mops-change-issuer - namespace: demo -spec: - type: ReconfigureTLS - databaseRef: - name: mg-rs - tls: - issuerRef: - name: mg-new-issuer - kind: Issuer - apiGroup: "cert-manager.io" diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml similarity index 63% rename from docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml rename to docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml index 25ed1b09e4..259a184c02 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/mops-add-tls.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml @@ -1,21 +1,24 @@ apiVersion: ops.kubedb.com/v1alpha1 -kind: MongoDBOpsRequest +kind: MSSQLServerOpsRequest metadata: - name: mops-add-tls + name: msops-add-tls namespace: demo spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: issuerRef: - name: mg-issuer + name: mssqlserver-ca-issuer kind: Issuer apiGroup: "cert-manager.io" certificates: - alias: client subject: organizations: - - mongo + - mssqlserver organizationalUnits: - client + clientTLS: true + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-change-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-change-issuer.yaml new file mode 100644 index 0000000000..477062a59a --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-change-issuer.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-change-issuer + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: ms-standalone + tls: + issuerRef: + name: mssqlserver-new-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-remove.yaml similarity index 56% rename from docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml rename to docs/examples/mssqlserver/reconfigure-tls/msops-remove.yaml index 06245506d9..348381419d 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-remove.yaml @@ -1,11 +1,11 @@ apiVersion: ops.kubedb.com/v1alpha1 -kind: MongoDBOpsRequest +kind: MSSQLServerOpsRequest metadata: - name: mops-remove + name: msops-remove namespace: demo spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: - remove: true + remove: true \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml similarity index 58% rename from docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml rename to docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml index 7530796118..9890457f39 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml @@ -1,11 +1,13 @@ apiVersion: ops.kubedb.com/v1alpha1 -kind: MongoDBOpsRequest +kind: MSSQLServerOpsRequest metadata: - name: mops-rotate + name: msops-rotate namespace: demo spec: type: ReconfigureTLS databaseRef: - name: mg-rs + name: ms-standalone tls: rotateCertificates: true + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml index 066cbce511..2941ec2e2a 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml @@ -1,8 +1,8 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: - name: mg-new-issuer + name: mssqlserver-new-ca-issuer namespace: demo spec: ca: - secretName: mongo-new-ca + secretName: mssqlserver-new-ca \ No newline at end of file diff --git a/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md b/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md similarity index 87% rename from docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md rename to docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md index dfcf1ad384..3097a46171 100644 --- a/docs/guides/mssqlserver/reconfigure-tls/reconfigure-tls.md +++ b/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md @@ -1,20 +1,20 @@ --- -title: Reconfigure MSSQLServer TLS/SSL Encryption +title: Reconfigure MSSQLServer Availability Group TLS/SSL Encryption menu: docs_{{ .version }}: - identifier: ms-reconfigure-tls-standalone - name: Standalone + identifier: ms-reconfigure-tls-ag-cluster + name: Availability Group (HA Cluster) parent: ms-reconfigure-tls - weight: 20 + weight: 30 menu_name: docs_{{ .version }} section_menu_id: guides --- > New to KubeDB? Please start [here](/docs/README.md). -# Reconfigure Standalone MSSQLServer TLS/SSL (Transport Encryption) +# Reconfigure MSSQLServer Availability Group TLS/SSL (Transport Encryption) -KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing MSSQLServer database via a MSSQLServerOpsRequest. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. +KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing MSSQLServer Availability Group Cluster database via a MSSQLServerOpsRequest. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. ## Before You Begin @@ -487,23 +487,19 @@ mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P l2mGQ We can verify from the above output that TLS is enabled for this database, `mssql.conf` file has tls configurations. So, TLS is enabled successfully to this database. - - - -start from here. .... - - ## Rotate Certificate Now we are going to rotate the certificate of this database. First let's check the current expiration date of the certificate. ```bash -$ kubectl exec -it ms-standalone-2 -n demo bash -root@ms-standalone-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout -notAfter=Jun 9 13:32:20 2021 GMT +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 13:11:02 2025 GMT +mssql@ms-standalone-0:/$ ``` -So, the certificate will expire on this time `Jun 9 13:32:20 2021 GMT`. +So, the certificate will expire on this time `Feb 16 13:11:02 2025 GMT`. + ### Create MSSQLServerOpsRequest @@ -513,7 +509,7 @@ Now we are going to increase it using a MSSQLServerOpsRequest. Below is the yaml apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-rotate + name: msops-rotate namespace: demo spec: type: ReconfigureTLS @@ -521,6 +517,8 @@ spec: name: ms-standalone tls: rotateCertificates: true + timeout: 5m + apply: IfReady ``` Here, @@ -532,8 +530,8 @@ Here, Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-rotate.yaml -mssqlserveropsrequest.ops.kubedb.com/mops-rotate created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-rotate created ``` #### Verify Certificate Rotated Successfully @@ -543,111 +541,117 @@ Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following co ```bash $ kubectl get mssqlserveropsrequest -n demo Every 2.0s: kubectl get mssqlserveropsrequest -n demo -NAME TYPE STATUS AGE -mops-rotate ReconfigureTLS Successful 112s +NAME TYPE STATUS AGE +msops-rotate ReconfigureTLS Successful 2m47s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo mops-rotate -Name: mops-rotate +$ kubectl describe mssqlserveropsrequest -n demo msops-rotate +Name: msops-rotate Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-11T16:17:55Z + Creation Timestamp: 2024-11-18T13:17:50Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:databaseRef: - .: - f:name: - f:tls: - .: - f:rotateCertificates: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-11T16:17:55Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-11T16:17:55Z - Resource Version: 521643 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-rotate - UID: 6d96ead2-a868-47d8-85fb-77eecc9a96b4 + Resource Version: 549743 + UID: af51934d-1fb4-4fa6-b254-46b1de199fae Spec: + Apply: IfReady Database Ref: - Name: ms-standalone + Name: ms-standalone + Timeout: 5m Tls: Rotate Certificates: true Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2021-03-11T16:17:55Z - Message: MSSQLServer ops request is reconfiguring TLS + Last Transition Time: 2024-11-18T13:17:50Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2021-03-11T16:17:55Z - Message: Successfully Added Issuing Condition in Certificates + Last Transition Time: 2024-11-18T13:17:50Z + Message: Successfully paused database Observed Generation: 1 - Reason: IssuingConditionUpdated + Reason: DatabasePauseSucceeded Status: True - Type: IssuingConditionUpdated - Last Transition Time: 2021-03-11T16:18:00Z - Message: Successfully Issued New Certificates + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T13:17:50Z + Message: successfully add issuing condition to all the certificates Observed Generation: 1 - Reason: CertificateIssuingSuccessful + Reason: IssueCertificatesSucceeded Status: True - Type: CertificateIssuingSuccessful - Last Transition Time: 2021-03-11T16:19:45Z - Message: Successfully Restarted ReplicaSet nodes + Type: IssueCertificatesSucceeded + Last Transition Time: 2024-11-18T13:18:00Z + Message: Successfully synced all certificates Observed Generation: 1 - Reason: RestartReplicaSet + Reason: CertificateSynced Status: True - Type: RestartReplicaSet - Last Transition Time: 2021-03-11T16:19:45Z - Message: Successfully Reconfigured TLS + Type: CertificateSynced + Last Transition Time: 2024-11-18T13:17:55Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-18T13:17:55Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-18T13:17:55Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-18T13:18:05Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T13:18:51Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T13:18:11Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:11Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:46Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:51Z + Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal CertificateIssuingSuccessful 2m10s KubeDB Ops-manager operator Successfully Issued New Certificates - Normal RestartReplicaSet 25s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes - Normal Successful 25s KubeDB Ops-manager operator Successfully Reconfigured TLS ``` Now, let's check the expiration date of the certificate. ```bash -$ kubectl exec -it ms-standalone-2 -n demo bash -root@ms-standalone-2:/# openssl x509 -in /var/run/mssqlserver/tls/client.pem -inform PEM -enddate -nameopt RFC2253 -noout -notAfter=Jun 9 16:17:55 2021 GMT +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 13:17:50 2025 GMT ``` As we can see from the above output, the certificate has been rotated successfully. @@ -670,14 +674,14 @@ writing new private key to './ca.key' - Now we are going to create a new ca-secret using the certificate files that we have just generated. ```bash -$ kubectl create secret tls mongo-new-ca \ - --cert=ca.crt \ - --key=ca.key \ - --namespace=demo -secret/mongo-new-ca created +$ kubectl create secret tls mssqlserver-new-ca \ + --cert=ca.crt \ + --key=ca.key \ + --namespace=demo +secret/mssqlserver-new-ca created ``` -Now, Let's create a new `Issuer` using the `mongo-new-ca` secret that we have just created. The `YAML` file looks like this: +Now, Let's create a new `Issuer` using the `mssqlserver-new-ca` secret that we have just created. The `YAML` file looks like this: ```yaml apiVersion: cert-manager.io/v1 @@ -687,7 +691,7 @@ metadata: namespace: demo spec: ca: - secretName: mongo-new-ca + secretName: mssqlserver-new-ca ``` Let's apply the `YAML` file: @@ -1015,17 +1019,12 @@ To cleanup the Kubernetes resources created by this tutorial, run: ```bash kubectl delete mssqlserver -n demo ms-standalone kubectl delete issuer -n demo ms-issuer ms-new-issuer -kubectl delete mssqlserveropsrequest msops-add-tls mops-remove mops-rotate mops-change-issuer +kubectl delete mssqlserveropsrequest msops-add-tls mops-remove msops-rotate mops-change-issuer kubectl delete ns demo ``` ## Next Steps - Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mssqlserver.md). -- Initialize [MSSQLServer with Script](/docs/guides/mssqlserver/initialization/using-script.md). - Monitor your MSSQLServer database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/mssqlserver/monitoring/using-prometheus-operator.md). -- Monitor your MSSQLServer database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/mssqlserver/monitoring/using-builtin-prometheus.md). -- Use [private Docker registry](/docs/guides/mssqlserver/private-registry/using-private-registry.md) to deploy MSSQLServer with KubeDB. -- Use [kubedb cli](/docs/guides/mssqlserver/cli/cli.md) to manage databases like kubectl for Kubernetes. -- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mongodb.md). - Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/mssqlserver/reconfigure-tls/standalone.md b/docs/guides/mssqlserver/reconfigure-tls/standalone.md new file mode 100644 index 0000000000..19f46f300e --- /dev/null +++ b/docs/guides/mssqlserver/reconfigure-tls/standalone.md @@ -0,0 +1,1008 @@ +--- +title: Reconfigure Standalone MSSQLServer TLS/SSL Encryption +menu: + docs_{{ .version }}: + identifier: ms-reconfigure-tls-standalone + name: Standalone + parent: ms-reconfigure-tls + weight: 20 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +> New to KubeDB? Please start [here](/docs/README.md). + +# Reconfigure Standalone MSSQLServer TLS/SSL (Transport Encryption) + +KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL certificates for existing MSSQLServer database via a MSSQLServerOpsRequest. This tutorial will show you how to use KubeDB to reconfigure TLS/SSL encryption. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +> Note: YAML files used in this tutorial are stored in [docs/examples/mssqlserver](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Add TLS to a MSSQLServer database + +Here, We are going to create a MSSQLServer database without TLS and then reconfigure the database to use TLS. + +At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + +### Deploy MSSQLServer without TLS + +In this section, we are going to deploy a MSSQLServer Standalone database without TLS. In the next few sections we will reconfigure TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: ms-standalone + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +Let's create the `MSSQLServer` CR we have shown above, + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml +mssqlserver.kubedb.com/ms-standalone created +``` + +Now, wait until `ms-standalone` has status `Ready`. i.e, + +```bash +$ kubectl get ms -n demo +NAME VERSION STATUS AGE +ms-standalone 2022-cu12 Ready 4m3s + +$ kubectl describe ms -n demo ms-standalone +Name: ms-standalone +Namespace: demo +Labels: +Annotations: +API Version: kubedb.com/v1alpha2 +Kind: MSSQLServer +Metadata: + Creation Timestamp: 2024-11-14T12:45:36Z + Finalizers: + kubedb.com + Generation: 2 + Resource Version: 438804 + UID: 83ebe191-3754-41af-8d86-ed211bf9c31c +Spec: + Auth Secret: + Name: ms-standalone-auth + Deletion Policy: WipeOut + Health Checker: + Failure Threshold: 1 + Period Seconds: 10 + Timeout Seconds: 10 + Pod Template: + Controller: + Metadata: + Spec: + Containers: + Env: + Name: ACCEPT_EULA + Value: Y + Name: MSSQL_PID + Value: Evaluation + Name: mssql + Resources: + Limits: + Memory: 4Gi + Requests: + Cpu: 500m + Memory: 4Gi + Security Context: + Allow Privilege Escalation: false + Capabilities: + Add: + NET_BIND_SERVICE + Drop: + ALL + Run As Group: 10001 + Run As Non Root: true + Run As User: 10001 + Seccomp Profile: + Type: RuntimeDefault + Init Containers: + Name: mssql-init + Resources: + Limits: + Memory: 512Mi + Requests: + Cpu: 200m + Memory: 512Mi + Security Context: + Allow Privilege Escalation: false + Capabilities: + Drop: + ALL + Run As Group: 10001 + Run As Non Root: true + Run As User: 10001 + Seccomp Profile: + Type: RuntimeDefault + Pod Placement Policy: + Name: default + Security Context: + Fs Group: 10001 + Replicas: 1 + Storage: + Access Modes: + ReadWriteOnce + Resources: + Requests: + Storage: 1Gi + Storage Class Name: standard + Storage Type: Durable + Tls: + Certificates: + Alias: server + Secret Name: ms-standalone-server-cert + Subject: + Organizational Units: + server + Organizations: + kubedb + Alias: client + Secret Name: ms-standalone-client-cert + Subject: + Organizational Units: + client + Organizations: + kubedb + Client TLS: false + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mssqlserver-ca-issuer + Version: 2022-cu12 +Status: + Conditions: + Last Transition Time: 2024-11-14T12:45:36Z + Message: The KubeDB operator has started the provisioning of MSSQLServer: demo/ms-standalone + Observed Generation: 1 + Reason: DatabaseProvisioningStartedSuccessfully + Status: True + Type: ProvisioningStarted + Last Transition Time: 2024-11-14T12:46:36Z + Message: All replicas are ready for MSSQLServer demo/ms-standalone + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: ReplicaReady + Last Transition Time: 2024-11-14T12:46:46Z + Message: database demo/ms-standalone is accepting connection + Observed Generation: 2 + Reason: AcceptingConnection + Status: True + Type: AcceptingConnection + Last Transition Time: 2024-11-14T12:46:46Z + Message: database demo/ms-standalone is ready + Observed Generation: 2 + Reason: AllReplicasReady + Status: True + Type: Ready + Last Transition Time: 2024-11-14T12:47:06Z + Message: The MSSQLServer: demo/ms-standalone is successfully provisioned. + Observed Generation: 2 + Reason: DatabaseSuccessfullyProvisioned + Status: True + Type: Provisioned + Phase: Ready +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer server certificates + Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer client certificates + +``` + +Now, connect to this database by exec into a pod and verify the TLS is disabled. + +> when we connect using the sqlcmd tool, the -N option is available with [s|m|o] parameters, where 's' stands for strict, 'm' for mandatory, and 'o' for optional. The default setting is mandatory. + + +```bash +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\username}' | base64 -d +sa + +$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\password}' | base64 -d +b1HLv9EV4CaSalX6 + +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate]. +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Client unable to establish connection. + + +So Now, we have to connect with -C [Trust Server Certificate] +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N -C +1> +``` + +We can verify from the above output that TLS is disabled for this database, `mssql.conf` file has no tls configuration. + +Now we will enable tls configuration using MSSQLServerOpsRequest +### Create MSSQLServerOpsRequest + +In order to add TLS to the database, we have to create a `MSSQLServerOpsRequest` CRO with our issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: ms-standalone + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: client + subject: + organizations: + - mssqlserver + organizationalUnits: + - client + clientTLS: true + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.issuerRef` specifies the issuer name, kind and api group. +- `spec.tls.certificates` specifies the certificates. You can learn more about this field from [here](/docs/guides/mssqlserver/concepts/mssqlserver.md#spectls). + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-add-tls created +``` + +#### Verify TLS Enabled Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ watch kubectl get msops -n demo +Every 2.0s: kubectl get msops -n demo + +NAME TYPE STATUS AGE +msops-add-tls ReconfigureTLS Successful 115s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-add-tls +Name: msops-add-tls +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-15T11:48:03Z + Generation: 1 + Resource Version: 491162 + UID: 007ad725-0a3f-4290-8814-d85592cfc247 +Spec: + Apply: IfReady + Database Ref: + Name: ms-standalone + Timeout: 5m + Tls: + Certificates: + Alias: client + Subject: + Organizational Units: + client + Organizations: + mssqlserver + Client TLS: true + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mssqlserver-ca-issuer + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2024-11-15T11:48:03Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2024-11-15T11:48:06Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-15T11:48:16Z + Message: Successfully synced all certificates + Observed Generation: 1 + Reason: CertificateSynced + Status: True + Type: CertificateSynced + Last Transition Time: 2024-11-15T11:48:11Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-15T11:48:11Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-15T11:48:11Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-15T11:48:21Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-15T11:49:06Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-15T11:48:26Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-15T11:48:26Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-15T11:49:01Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-15T11:49:07Z + Message: Successfully completed reconfigureTLS for mssqlserver. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +``` + +Now, Let's exec into a database node + + + +```bash +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ ls /var/opt/mssql/tls +ca.crt client.crt client.key server.crt server.key +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -subject -nameopt RFC2253 -noout +subject=CN=mssql,OU=client,O=mssqlserver +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +[network] +forceencryption = 1 +tlscert = /var/opt/mssql/tls/server.crt +tlskey = /var/opt/mssql/tls/server.key +tlsprotocols = 1.2,1.1,1.0 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P l2mGQRMETAS96QRb -N +1> +``` + +We can verify from the above output that TLS is enabled for this database, `mssql.conf` file has tls configurations. So, TLS is enabled successfully to this database. + + +## Rotate Certificate + +Now we are going to rotate the certificate of this database. First let's check the current expiration date of the certificate. + +```bash +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 13:11:02 2025 GMT +mssql@ms-standalone-0:/$ +``` + +So, the certificate will expire on this time `Feb 16 13:11:02 2025 GMT`. + + +### Create MSSQLServerOpsRequest + +Now we are going to increase it using a MSSQLServerOpsRequest. Below is the yaml of the ops request that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-rotate + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: ms-standalone + tls: + rotateCertificates: true + timeout: 5m + apply: IfReady +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this database. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-rotate created +``` + +#### Verify Certificate Rotated Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +msops-rotate ReconfigureTLS Successful 2m47s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-rotate +Name: msops-rotate +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-18T13:17:50Z + Generation: 1 + Resource Version: 549743 + UID: af51934d-1fb4-4fa6-b254-46b1de199fae +Spec: + Apply: IfReady + Database Ref: + Name: ms-standalone + Timeout: 5m + Tls: + Rotate Certificates: true + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2024-11-18T13:17:50Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2024-11-18T13:17:50Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T13:17:50Z + Message: successfully add issuing condition to all the certificates + Observed Generation: 1 + Reason: IssueCertificatesSucceeded + Status: True + Type: IssueCertificatesSucceeded + Last Transition Time: 2024-11-18T13:18:00Z + Message: Successfully synced all certificates + Observed Generation: 1 + Reason: CertificateSynced + Status: True + Type: CertificateSynced + Last Transition Time: 2024-11-18T13:17:55Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-18T13:17:55Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-18T13:17:55Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-18T13:18:05Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T13:18:51Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T13:18:11Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:11Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:46Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-18T13:18:51Z + Message: Successfully completed reconfigureTLS for mssqlserver. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +``` + +Now, let's check the expiration date of the certificate. + +```bash +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 13:17:50 2025 GMT +``` + +As we can see from the above output, the certificate has been rotated successfully. + +## Change Issuer/ClusterIssuer + +Now, we are going to change the issuer of this database. + +- Let's create a new ca certificate and key using a different subject `CN=ca-update,O=kubedb-updated`. + +```bash +$ openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=ca-updated/O=kubedb-updated" +Generating a RSA private key +..............................................................+++++ +......................................................................................+++++ +writing new private key to './ca.key' +----- +``` + +- Now we are going to create a new ca-secret using the certificate files that we have just generated. + +```bash +$ kubectl create secret tls mssqlserver-new-ca \ + --cert=ca.crt \ + --key=ca.key \ + --namespace=demo +secret/mssqlserver-new-ca created +``` + +Now, Let's create a new `Issuer` using the `mongo-new-ca` secret that we have just created. The `YAML` file looks like this: + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-new-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-new-ca +``` + +Let's apply the `YAML` file: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml +issuer.cert-manager.io/mssqlserver-new-ca-issuer created +``` + +### Create MSSQLServerOpsRequest + +In order to use the new issuer to issue new certificates, we have to create a `MSSQLServerOpsRequest` CRO with the newly created issuer. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-change-issuer + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: ms-standalone + tls: + issuerRef: + name: mssqlserver-new-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.issuerRef` specifies the issuer name, kind and api group. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-change-issuer.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-change-issuer created +``` + +#### Verify Issuer is changed successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +msops-change-issuer ReconfigureTLS Successful 3m28s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-change-issuer +Name: msops-change-issuer +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-18T13:38:48Z + Generation: 1 + Resource Version: 551920 + UID: 551ce6a4-742a-43ed-a994-be4ba4809bca +Spec: + Apply: IfReady + Database Ref: + Name: ms-standalone + Tls: + Issuer Ref: + API Group: cert-manager.io + Kind: Issuer + Name: mssqlserver-new-ca-issuer + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2024-11-18T13:38:48Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2024-11-18T13:38:51Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T13:39:01Z + Message: Successfully synced all certificates + Observed Generation: 1 + Reason: CertificateSynced + Status: True + Type: CertificateSynced + Last Transition Time: 2024-11-18T13:38:56Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-18T13:38:56Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-18T13:38:56Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-18T13:39:06Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T13:42:11Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T13:39:11Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:39:11Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:42:06Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-18T13:42:11Z + Message: Successfully completed reconfigureTLS for mssqlserver. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +``` + +Now, Lets exec into a database node and find out the ca subject to see if it matches the one we have provided. + +```bash +$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash +mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout +subject=O=kubedb-updated,CN=ca-updated +``` + +We can see from the above output that, the subject name matches the subject name of the new ca certificate that we have created. So, the issuer is changed successfully. + +## Remove TLS from the Database + +Now, we are going to remove TLS from this database using a MSSQLServerOpsRequest. + +### Create MSSQLServerOpsRequest + +Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, + +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-remove + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: ms-standalone + tls: + remove: true +``` + +Here, + +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.type` specifies that we are performing `ReconfigureTLS` on our database. +- `spec.tls.remove` specifies that we want to remove tls from this database. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-remove.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-remove created +``` + +#### Verify TLS Removed Successfully + +Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, + +```bash +$ watch kubectl get mssqlserveropsrequest -n demo +Every 2.0s: kubectl get mssqlserveropsrequest -n demo +NAME TYPE STATUS AGE +msops-remove ReconfigureTLS Successful 2m36s +``` + +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. + +```bash +$ kubectl describe mssqlserveropsrequest -n demo msops-remove +Name: msops-remove +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2024-11-18T13:49:15Z + Generation: 1 + Resource Version: 552812 + UID: 7e4b9c39-7fd2-44f6-9972-367c95198105 +Spec: + Apply: IfReady + Database Ref: + Name: ms-standalone + Tls: + Remove: true + Type: ReconfigureTLS +Status: + Conditions: + Last Transition Time: 2024-11-18T13:49:15Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes + Observed Generation: 1 + Reason: ReconfigureTLS + Status: True + Type: ReconfigureTLS + Last Transition Time: 2024-11-18T13:49:42Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T13:49:47Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T13:51:32Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T13:49:52Z + Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: GetPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:49:52Z + Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: EvictPod--ms-standalone-0 + Last Transition Time: 2024-11-18T13:51:27Z + Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--ms-standalone-0 + Last Transition Time: 2024-11-18T13:51:32Z + Message: Successfully completed reconfigureTLS for mssqlserver. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +``` + + +Now, Lets exec into the pod find out that TLS is disabled or not. +```bash +$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash +mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P b1HLv9EV4CaSalX6 -N +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate]. +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Client unable to establish connection. + +So Now, we have to connect with -C [Trust Server Certificate] +mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P b1HLv9EV4CaSalX6 -N -C +1> +``` + +We can verify from the above output that TLS is disabled for this database, `mssql.conf` file has no tls configuration. + +## Cleaning up + +To clean up the Kubernetes resources created by this tutorial, run: + +```bash +kubectl delete mssqlserver -n demo ms-standalone +kubectl delete issuer -n demo mssqlserver-ca-issuer mssqlserver-new-ca-issuer +kubectl delete mssqlserveropsrequest msops-add-tls msops-remove msops-rotate msops-change-issuer +kubectl delete ns demo +``` + +## Next Steps + +- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mssqlserver.md). +- Monitor your MSSQLServer database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/mssqlserver/monitoring/using-prometheus-operator.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). From eecfd883245ac55a134af4209290b58797cf9f07 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Mon, 18 Nov 2024 21:10:17 +0600 Subject: [PATCH 10/14] Finish reconfigure tls for ag Signed-off-by: Neaj Morshad --- .../reconfigure-tls/mg-replicaset.yaml | 17 - .../reconfigure-tls/msops-ag-add-tls.yaml | 24 + .../msops-ag-change-issuer.yaml | 14 + .../reconfigure-tls/msops-ag-remove.yaml | 11 + .../reconfigure-tls/msops-ag-rotate.yaml | 13 + .../msops-reconfigure-ag-apply.yaml | 16 - .../reconfigure-tls/msops-reconfigure-ag.yaml | 14 - .../msops-reconfigure-standalone-apply.yaml | 16 - .../msops-reconfigure-standalone.yaml | 14 - ...-ag-cluster.yaml => mssql-ag-cluster.yaml} | 12 +- .../mssqlserver/reconfigure-tls/ag_cluster.md | 766 +++++++++--------- 11 files changed, 434 insertions(+), 483 deletions(-) delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-ag-add-tls.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-ag-change-issuer.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-ag-remove.yaml create mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-ag-rotate.yaml delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml delete mode 100644 docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml rename docs/examples/mssqlserver/reconfigure-tls/{mssqlserver-ag-cluster.yaml => mssql-ag-cluster.yaml} (77%) diff --git a/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml b/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml deleted file mode 100644 index b271b8a5f2..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/mg-replicaset.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: kubedb.com/v1 -kind: MongoDB -metadata: - name: mg-rs - namespace: demo -spec: - version: "4.4.26" - replicas: 3 - replicaSet: - name: rs0 - storage: - storageClassName: "standard" - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-ag-add-tls.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-add-tls.yaml new file mode 100644 index 0000000000..42904f0309 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-add-tls.yaml @@ -0,0 +1,24 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-ag-add-tls + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mssql-ag-cluster + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + certificates: + - alias: client + subject: + organizations: + - mssqlserver + organizationalUnits: + - client + clientTLS: true + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-ag-change-issuer.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-change-issuer.yaml new file mode 100644 index 0000000000..0d8b199efc --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-change-issuer.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-ag-change-issuer + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mssql-ag-cluster + tls: + issuerRef: + name: mssqlserver-new-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-ag-remove.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-remove.yaml new file mode 100644 index 0000000000..338985c3d9 --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-remove.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-ag-remove + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mssql-ag-cluster + tls: + remove: true \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-ag-rotate.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-rotate.yaml new file mode 100644 index 0000000000..31bc701f8e --- /dev/null +++ b/docs/examples/mssqlserver/reconfigure-tls/msops-ag-rotate.yaml @@ -0,0 +1,13 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-ag-rotate + namespace: demo +spec: + type: ReconfigureTLS + databaseRef: + name: mssql-ag-cluster + tls: + rotateCertificates: true + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml deleted file mode 100644 index b93d450d54..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag-apply.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: ops.kubedb.com/v1alpha1 -kind: MSSQLServerOpsRequest -metadata: - name: msops-reconfigure-ag-apply - namespace: demo -spec: - type: Reconfigure - databaseRef: - name: mssqlserver-ag-cluster - configuration: - applyConfig: - mssql.conf: |- - [memory] - memorylimitmb = 3072 - timeout: 5m - apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml deleted file mode 100644 index 86d2b8283d..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-ag.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: ops.kubedb.com/v1alpha1 -kind: MSSQLServerOpsRequest -metadata: - name: msops-reconfigure-ag - namespace: demo -spec: - type: Reconfigure - databaseRef: - name: mssqlserver-ag-cluster - configuration: - configSecret: - name: new-custom-config - timeout: 5m - apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml deleted file mode 100644 index 0199028a1b..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone-apply.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: ops.kubedb.com/v1alpha1 -kind: MSSQLServerOpsRequest -metadata: - name: msops-reconfigure-standalone-apply - namespace: demo -spec: - type: Reconfigure - databaseRef: - name: ms-standalone - configuration: - applyConfig: - mssql.conf: |- - [memory] - memorylimitmb = 3072 - timeout: 5m - apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml b/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml deleted file mode 100644 index 5c0f52531a..0000000000 --- a/docs/examples/mssqlserver/reconfigure-tls/msops-reconfigure-standalone.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: ops.kubedb.com/v1alpha1 -kind: MSSQLServerOpsRequest -metadata: - name: msops-reconfigure-standalone - namespace: demo -spec: - type: Reconfigure - databaseRef: - name: ms-standalone - configuration: - configSecret: - name: new-custom-config - timeout: 5m - apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml b/docs/examples/mssqlserver/reconfigure-tls/mssql-ag-cluster.yaml similarity index 77% rename from docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml rename to docs/examples/mssqlserver/reconfigure-tls/mssql-ag-cluster.yaml index 8407bb6fcf..95212e5c57 100644 --- a/docs/examples/mssqlserver/reconfigure-tls/mssqlserver-ag-cluster.yaml +++ b/docs/examples/mssqlserver/reconfigure-tls/mssql-ag-cluster.yaml @@ -1,12 +1,10 @@ apiVersion: kubedb.com/v1alpha2 kind: MSSQLServer metadata: - name: mssqlserver-ag-cluster + name: mssql-ag-cluster namespace: demo spec: version: "2022-cu12" - configSecret: - name: ms-custom-config replicas: 3 topology: mode: AvailabilityGroup @@ -28,7 +26,13 @@ spec: - name: ACCEPT_EULA value: "Y" - name: MSSQL_PID - value: Developer + value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" storageType: Durable storage: storageClassName: "standard" diff --git a/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md b/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md index 3097a46171..7a17b63d4c 100644 --- a/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md +++ b/docs/guides/mssqlserver/reconfigure-tls/ag_cluster.md @@ -33,9 +33,9 @@ KubeDB supports reconfigure i.e. add, remove, update and rotation of TLS/SSL cer > Note: YAML files used in this tutorial are stored in [docs/examples/mssqlserver](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). -## Add TLS to a MSSQLServer database +## Add TLS to a MSSQLServer Availability Group Cluster -Here, We are going to create a MSSQLServer database without TLS and then reconfigure the database to use TLS. +Here, We are going to create a MSSQLServer Availability Group Cluster without TLS and then reconfigure the database to use TLS. At first, we need to create an Issuer/ClusterIssuer which will be used to generate the certificate used for TLS configurations. @@ -74,17 +74,23 @@ issuer.cert-manager.io/mssqlserver-ca-issuer created ### Deploy MSSQLServer without TLS -In this section, we are going to deploy a MSSQLServer Standalone database without TLS. In the next few sections we will reconfigure TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, +In this section, we are going to deploy a MSSQLServer Availability Group Cluster without TLS. In the next few sections we will reconfigure to add TLS using `MSSQLServerOpsRequest` CRD. Below is the YAML of the `MSSQLServer` CR that we are going to create, ```yaml apiVersion: kubedb.com/v1alpha2 kind: MSSQLServer metadata: - name: ms-standalone + name: mssql-ag-cluster namespace: demo spec: version: "2022-cu12" - replicas: 1 + replicas: 3 + topology: + mode: AvailabilityGroup + availabilityGroup: + databases: + - agdb1 + - agdb2 tls: issuerRef: name: mssqlserver-ca-issuer @@ -100,6 +106,12 @@ spec: value: "Y" - name: MSSQL_PID value: Evaluation + resources: + requests: + cpu: "500m" + memory: "1.5Gi" + limits: + memory: "2Gi" storageType: Durable storage: storageClassName: "standard" @@ -114,160 +126,16 @@ spec: Let's create the `MSSQLServer` CR we have shown above, ```bash -$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/ms-standalone.yaml -mssqlserver.kubedb.com/ms-standalone created +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mssql-ag-cluster.yaml +mssqlserver.kubedb.com/mssql-ag-cluster created ``` -Now, wait until `ms-standalone` has status `Ready`. i.e, +Now, wait until `mssql-ag-cluster` has status `Ready`. i.e, ```bash $ kubectl get ms -n demo -NAME VERSION STATUS AGE -ms-standalone 2022-cu12 Ready 4m3s - -$ kubectl describe ms -n demo ms-standalone -Name: ms-standalone -Namespace: demo -Labels: -Annotations: -API Version: kubedb.com/v1alpha2 -Kind: MSSQLServer -Metadata: - Creation Timestamp: 2024-11-14T12:45:36Z - Finalizers: - kubedb.com - Generation: 2 - Resource Version: 438804 - UID: 83ebe191-3754-41af-8d86-ed211bf9c31c -Spec: - Auth Secret: - Name: ms-standalone-auth - Deletion Policy: WipeOut - Health Checker: - Failure Threshold: 1 - Period Seconds: 10 - Timeout Seconds: 10 - Pod Template: - Controller: - Metadata: - Spec: - Containers: - Env: - Name: ACCEPT_EULA - Value: Y - Name: MSSQL_PID - Value: Evaluation - Name: mssql - Resources: - Limits: - Memory: 4Gi - Requests: - Cpu: 500m - Memory: 4Gi - Security Context: - Allow Privilege Escalation: false - Capabilities: - Add: - NET_BIND_SERVICE - Drop: - ALL - Run As Group: 10001 - Run As Non Root: true - Run As User: 10001 - Seccomp Profile: - Type: RuntimeDefault - Init Containers: - Name: mssql-init - Resources: - Limits: - Memory: 512Mi - Requests: - Cpu: 200m - Memory: 512Mi - Security Context: - Allow Privilege Escalation: false - Capabilities: - Drop: - ALL - Run As Group: 10001 - Run As Non Root: true - Run As User: 10001 - Seccomp Profile: - Type: RuntimeDefault - Pod Placement Policy: - Name: default - Security Context: - Fs Group: 10001 - Replicas: 1 - Storage: - Access Modes: - ReadWriteOnce - Resources: - Requests: - Storage: 1Gi - Storage Class Name: standard - Storage Type: Durable - Tls: - Certificates: - Alias: server - Secret Name: ms-standalone-server-cert - Subject: - Organizational Units: - server - Organizations: - kubedb - Alias: client - Secret Name: ms-standalone-client-cert - Subject: - Organizational Units: - client - Organizations: - kubedb - Client TLS: false - Issuer Ref: - API Group: cert-manager.io - Kind: Issuer - Name: mssqlserver-ca-issuer - Version: 2022-cu12 -Status: - Conditions: - Last Transition Time: 2024-11-14T12:45:36Z - Message: The KubeDB operator has started the provisioning of MSSQLServer: demo/ms-standalone - Observed Generation: 1 - Reason: DatabaseProvisioningStartedSuccessfully - Status: True - Type: ProvisioningStarted - Last Transition Time: 2024-11-14T12:46:36Z - Message: All replicas are ready for MSSQLServer demo/ms-standalone - Observed Generation: 2 - Reason: AllReplicasReady - Status: True - Type: ReplicaReady - Last Transition Time: 2024-11-14T12:46:46Z - Message: database demo/ms-standalone is accepting connection - Observed Generation: 2 - Reason: AcceptingConnection - Status: True - Type: AcceptingConnection - Last Transition Time: 2024-11-14T12:46:46Z - Message: database demo/ms-standalone is ready - Observed Generation: 2 - Reason: AllReplicasReady - Status: True - Type: Ready - Last Transition Time: 2024-11-14T12:47:06Z - Message: The MSSQLServer: demo/ms-standalone is successfully provisioned. - Observed Generation: 2 - Reason: DatabaseSuccessfullyProvisioned - Status: True - Type: Provisioned - Phase: Ready -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer server certificates - Normal Successful 4m20s KubeDB Ops-manager Operator Successfully created MSSQLServer client certificates - +NAME VERSION STATUS AGE +mssql-ag-cluster 2022-cu12 Ready 4m38s ``` Now, connect to this database by exec into a pod and verify the TLS is disabled. @@ -276,23 +144,22 @@ Now, connect to this database by exec into a pod and verify the TLS is disabled. ```bash -$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\username}' | base64 -d +$ kubectl get secrets -n demo mssql-ag-cluster-auth -o jsonpath='{.data.\username}' | base64 -d sa -$ kubectl get secrets -n demo ms-standalone-auth -o jsonpath='{.data.\password}' | base64 -d -b1HLv9EV4CaSalX6 +$ kubectl get secrets -n demo mssql-ag-cluster-auth -o jsonpath='{.data.\password}' | base64 -d +Q9kDWVQMnawLcnZq -$ kubectl exec -it -n demo ms-standalone-0 -c mssql -- bash -mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +$ kubectl exec -it -n demo mssql-ag-cluster-0 -c mssql -- bash +mssql@mssql-ag-cluster-0:/$ cat /var/opt/mssql/mssql.conf [language] lcid = 1033 -mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N +mssql@mssql-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "Q9kDWVQMnawLcnZq" -N Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate]. Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Client unable to establish connection. - So Now, we have to connect with -C [Trust Server Certificate] -mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "b1HLv9EV4CaSalX6" -N -C +mssql@mssql-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "Q9kDWVQMnawLcnZq" -N -C 1> ``` @@ -307,12 +174,12 @@ In order to add TLS to the database, we have to create a `MSSQLServerOpsRequest` apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: msops-add-tls + name: msops-ag-add-tls namespace: demo spec: type: ReconfigureTLS databaseRef: - name: ms-standalone + name: mssql-ag-cluster tls: issuerRef: name: mssqlserver-ca-issuer @@ -332,7 +199,7 @@ spec: Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mssql-ag-cluster` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.issuerRef` specifies the issuer name, kind and api group. - `spec.tls.certificates` specifies the certificates. You can learn more about this field from [here](/docs/guides/mssqlserver/concepts/mssqlserver.md#spectls). @@ -340,8 +207,8 @@ Here, Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-add-tls.yaml -mssqlserveropsrequest.ops.kubedb.com/msops-add-tls created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-ag-add-tls.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-ag-add-tls created ``` #### Verify TLS Enabled Successfully @@ -351,30 +218,29 @@ Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following co ```bash $ watch kubectl get msops -n demo Every 2.0s: kubectl get msops -n demo - -NAME TYPE STATUS AGE -msops-add-tls ReconfigureTLS Successful 115s +NAME TYPE STATUS AGE +msops-ag-add-tls ReconfigureTLS Successful 3m32s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo msops-add-tls -Name: msops-add-tls +$ kubectl describe mssqlserveropsrequest -n demo msops-ag-add-tls +Name: msops-ag-add-tls Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2024-11-15T11:48:03Z + Creation Timestamp: 2024-11-18T14:13:46Z Generation: 1 - Resource Version: 491162 - UID: 007ad725-0a3f-4290-8814-d85592cfc247 + Resource Version: 555629 + UID: 329b1815-6002-4d20-8df8-662ec6bedb2a Spec: Apply: IfReady Database Ref: - Name: ms-standalone + Name: mssql-ag-cluster Timeout: 5m Tls: Certificates: @@ -392,67 +258,97 @@ Spec: Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2024-11-15T11:48:03Z + Last Transition Time: 2024-11-18T14:13:46Z Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2024-11-15T11:48:06Z + Last Transition Time: 2024-11-18T14:13:49Z Message: Successfully paused database Observed Generation: 1 Reason: DatabasePauseSucceeded Status: True Type: DatabasePauseSucceeded - Last Transition Time: 2024-11-15T11:48:16Z + Last Transition Time: 2024-11-18T14:13:59Z Message: Successfully synced all certificates Observed Generation: 1 Reason: CertificateSynced Status: True Type: CertificateSynced - Last Transition Time: 2024-11-15T11:48:11Z + Last Transition Time: 2024-11-18T14:13:54Z Message: get certificate; ConditionStatus:True Observed Generation: 1 Status: True Type: GetCertificate - Last Transition Time: 2024-11-15T11:48:11Z + Last Transition Time: 2024-11-18T14:13:54Z Message: check ready condition; ConditionStatus:True Observed Generation: 1 Status: True Type: CheckReadyCondition - Last Transition Time: 2024-11-15T11:48:11Z + Last Transition Time: 2024-11-18T14:13:54Z Message: issuing condition; ConditionStatus:True Observed Generation: 1 Status: True Type: IssuingCondition - Last Transition Time: 2024-11-15T11:48:21Z + Last Transition Time: 2024-11-18T14:14:04Z Message: successfully reconciled the MSSQLServer with tls configuration Observed Generation: 1 Reason: UpdatePetSets Status: True Type: UpdatePetSets - Last Transition Time: 2024-11-15T11:49:06Z + Last Transition Time: 2024-11-18T14:16:10Z Message: Successfully restarted all nodes Observed Generation: 1 Reason: RestartNodes Status: True Type: RestartNodes - Last Transition Time: 2024-11-15T11:48:26Z - Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Last Transition Time: 2024-11-18T14:14:10Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:14:10Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:14:45Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:14:50Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:14:50Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:15:25Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:15:30Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 Observed Generation: 1 Status: True - Type: GetPod--ms-standalone-0 - Last Transition Time: 2024-11-15T11:48:26Z - Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Type: GetPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:15:30Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 Observed Generation: 1 Status: True - Type: EvictPod--ms-standalone-0 - Last Transition Time: 2024-11-15T11:49:01Z - Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Type: EvictPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:16:05Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 Observed Generation: 1 Status: True - Type: CheckPodRunning--ms-standalone-0 - Last Transition Time: 2024-11-15T11:49:07Z + Type: CheckPodRunning--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:16:10Z Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful @@ -464,15 +360,12 @@ Status: Now, Let's exec into a database node - - ```bash -$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash -mssql@ms-standalone-0:/$ ls /var/opt/mssql/tls -ca.crt client.crt client.key server.crt server.key -mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -subject -nameopt RFC2253 -noout +$ kubectl exec -it mssql-ag-cluster-0 -n demo -c mssql -- bash +mssql@mssql-ag-cluster-0:/$ ls /var/opt/mssql/tls +mssql@mssql-ag-cluster-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -subject -nameopt RFC2253 -noout subject=CN=mssql,OU=client,O=mssqlserver -mssql@ms-standalone-0:/$ cat /var/opt/mssql/mssql.conf +mssql@mssql-ag-cluster-0:/$ cat /var/opt/mssql/mssql.conf [language] lcid = 1033 [network] @@ -480,7 +373,7 @@ forceencryption = 1 tlscert = /var/opt/mssql/tls/server.crt tlskey = /var/opt/mssql/tls/server.key tlsprotocols = 1.2,1.1,1.0 -mssql@ms-standalone-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P l2mGQRMETAS96QRb -N +mssql@mssql-ag-cluster-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Q9kDWVQMnawLcnZq -N 1> ``` @@ -492,10 +385,10 @@ We can verify from the above output that TLS is enabled for this database, `mssq Now we are going to rotate the certificate of this database. First let's check the current expiration date of the certificate. ```bash -$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash -mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout -notAfter=Feb 16 13:11:02 2025 GMT -mssql@ms-standalone-0:/$ +$ kubectl exec -it mssql-ag-cluster-0 -n demo -c mssql -- bash +mssql@mssql-ag-cluster-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 14:13:49 2025 GMT +mssql@mssql-ag-cluster-0:/$ ``` So, the certificate will expire on this time `Feb 16 13:11:02 2025 GMT`. @@ -509,12 +402,12 @@ Now we are going to increase it using a MSSQLServerOpsRequest. Below is the yaml apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: msops-rotate + name: msops-ag-rotate namespace: demo spec: type: ReconfigureTLS databaseRef: - name: ms-standalone + name: mssql-ag-cluster tls: rotateCertificates: true timeout: 5m @@ -523,15 +416,15 @@ spec: Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mssql-ag-cluster` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.rotateCertificates` specifies that we want to rotate the certificate of this database. Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-rotate.yaml -mssqlserveropsrequest.ops.kubedb.com/msops-rotate created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-ag-rotate.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-ag-rotate created ``` #### Verify Certificate Rotated Successfully @@ -541,102 +434,132 @@ Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following co ```bash $ kubectl get mssqlserveropsrequest -n demo Every 2.0s: kubectl get mssqlserveropsrequest -n demo -NAME TYPE STATUS AGE -msops-rotate ReconfigureTLS Successful 2m47s +NAME TYPE STATUS AGE +msops-ag-rotate ReconfigureTLS Successful 5m14s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo msops-rotate -Name: msops-rotate +$ kubectl describe mssqlserveropsrequest -n demo msops-ag-rotate +Name: msops-ag-rotate Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2024-11-18T13:17:50Z + Creation Timestamp: 2024-11-18T14:36:38Z Generation: 1 - Resource Version: 549743 - UID: af51934d-1fb4-4fa6-b254-46b1de199fae + Resource Version: 558973 + UID: 54eca6e2-5e08-4730-a18a-1a754d2d8ea3 Spec: Apply: IfReady Database Ref: - Name: ms-standalone + Name: mssql-ag-cluster Timeout: 5m Tls: Rotate Certificates: true Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2024-11-18T13:17:50Z + Last Transition Time: 2024-11-18T14:36:38Z Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2024-11-18T13:17:50Z + Last Transition Time: 2024-11-18T14:36:54Z Message: Successfully paused database Observed Generation: 1 Reason: DatabasePauseSucceeded Status: True Type: DatabasePauseSucceeded - Last Transition Time: 2024-11-18T13:17:50Z + Last Transition Time: 2024-11-18T14:36:54Z Message: successfully add issuing condition to all the certificates Observed Generation: 1 Reason: IssueCertificatesSucceeded Status: True Type: IssueCertificatesSucceeded - Last Transition Time: 2024-11-18T13:18:00Z + Last Transition Time: 2024-11-18T14:37:04Z Message: Successfully synced all certificates Observed Generation: 1 Reason: CertificateSynced Status: True Type: CertificateSynced - Last Transition Time: 2024-11-18T13:17:55Z + Last Transition Time: 2024-11-18T14:36:59Z Message: get certificate; ConditionStatus:True Observed Generation: 1 Status: True Type: GetCertificate - Last Transition Time: 2024-11-18T13:17:55Z + Last Transition Time: 2024-11-18T14:36:59Z Message: check ready condition; ConditionStatus:True Observed Generation: 1 Status: True Type: CheckReadyCondition - Last Transition Time: 2024-11-18T13:17:55Z + Last Transition Time: 2024-11-18T14:36:59Z Message: issuing condition; ConditionStatus:True Observed Generation: 1 Status: True Type: IssuingCondition - Last Transition Time: 2024-11-18T13:18:05Z + Last Transition Time: 2024-11-18T14:37:09Z Message: successfully reconciled the MSSQLServer with tls configuration Observed Generation: 1 Reason: UpdatePetSets Status: True Type: UpdatePetSets - Last Transition Time: 2024-11-18T13:18:51Z + Last Transition Time: 2024-11-18T14:40:14Z Message: Successfully restarted all nodes Observed Generation: 1 Reason: RestartNodes Status: True Type: RestartNodes - Last Transition Time: 2024-11-18T13:18:11Z - Message: get pod; ConditionStatus:True; PodName:ms-standalone-0 + Last Transition Time: 2024-11-18T14:37:14Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:37:14Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:38:19Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:38:24Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 Status: True - Type: GetPod--ms-standalone-0 - Last Transition Time: 2024-11-18T13:18:11Z - Message: evict pod; ConditionStatus:True; PodName:ms-standalone-0 + Type: GetPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:38:24Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 Status: True - Type: EvictPod--ms-standalone-0 - Last Transition Time: 2024-11-18T13:18:46Z - Message: check pod running; ConditionStatus:True; PodName:ms-standalone-0 + Type: EvictPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:39:09Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 Status: True - Type: CheckPodRunning--ms-standalone-0 - Last Transition Time: 2024-11-18T13:18:51Z + Type: CheckPodRunning--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:39:14Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:39:14Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:40:09Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:40:14Z Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful @@ -649,9 +572,9 @@ Status: Now, let's check the expiration date of the certificate. ```bash -$ kubectl exec -it ms-standalone-0 -n demo -c mssql -- bash -mssql@ms-standalone-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout -notAfter=Feb 16 13:17:50 2025 GMT +$ kubectl exec -it mssql-ag-cluster-0 -n demo -c mssql -- bash +mssql@mssql-ag-cluster-0:/$ openssl x509 -in /var/opt/mssql/tls/client.crt -inform PEM -enddate -nameopt RFC2253 -noout +notAfter=Feb 16 14:36:54 2025 GMT ``` As we can see from the above output, the certificate has been rotated successfully. @@ -687,7 +610,7 @@ Now, Let's create a new `Issuer` using the `mssqlserver-new-ca` secret that we h apiVersion: cert-manager.io/v1 kind: Issuer metadata: - name: ms-new-issuer + name: mssqlserver-new-ca-issuer namespace: demo spec: ca: @@ -698,7 +621,7 @@ Let's apply the `YAML` file: ```bash $ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/new-issuer.yaml -issuer.cert-manager.io/ms-new-issuer created +issuer.cert-manager.io/mssqlserver-new-ca-issuer created ``` ### Create MSSQLServerOpsRequest @@ -709,30 +632,30 @@ In order to use the new issuer to issue new certificates, we have to create a `M apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-change-issuer + name: msops-ag-change-issuer namespace: demo spec: type: ReconfigureTLS databaseRef: - name: ms-standalone + name: mssql-ag-cluster tls: issuerRef: - name: ms-new-issuer + name: mssqlserver-new-ca-issuer kind: Issuer apiGroup: "cert-manager.io" ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mssql-ag-cluster` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.issuerRef` specifies the issuer name, kind and api group. Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-change-issuer.yaml -mssqlserveropsrequest.ops.kubedb.com/mops-change-issuer created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-ag-change-issuer.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-ag-change-issuer created ``` #### Verify Issuer is changed successfully @@ -742,111 +665,142 @@ Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following co ```bash $ kubectl get mssqlserveropsrequest -n demo Every 2.0s: kubectl get mssqlserveropsrequest -n demo -NAME TYPE STATUS AGE -mops-change-issuer ReconfigureTLS Successful 105s +NAME TYPE STATUS AGE +msops-ag-change-issuer ReconfigureTLS Successful 3m56s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo mops-change-issuer -Name: mops-change-issuer +$ kubectl describe mssqlserveropsrequest -n demo msops-ag-change-issuer +Name: msops-ag-change-issuer Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-11T16:27:47Z + Creation Timestamp: 2024-11-18T14:46:57Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:databaseRef: - .: - f:name: - f:tls: - .: - f:issuerRef: - .: - f:apiGroup: - f:kind: - f:name: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-11T16:27:47Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-11T16:27:47Z - Resource Version: 523903 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-change-issuer - UID: cdfe8a7d-52ef-466c-a5dd-97e74ad598ca + Resource Version: 560150 + UID: 5bf3e378-01b4-4dc9-aeeb-8cf5765aed10 Spec: + Apply: IfReady Database Ref: - Name: ms-standalone + Name: mssql-ag-cluster Tls: Issuer Ref: API Group: cert-manager.io Kind: Issuer - Name: ms-new-issuer + Name: mssqlserver-new-ca-issuer Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2021-03-11T16:27:47Z - Message: MSSQLServer ops request is reconfiguring TLS + Last Transition Time: 2024-11-18T14:46:57Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2021-03-11T16:27:52Z - Message: Successfully Issued New Certificates + Last Transition Time: 2024-11-18T14:47:00Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T14:47:10Z + Message: Successfully synced all certificates + Observed Generation: 1 + Reason: CertificateSynced + Status: True + Type: CertificateSynced + Last Transition Time: 2024-11-18T14:47:05Z + Message: get certificate; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: GetCertificate + Last Transition Time: 2024-11-18T14:47:05Z + Message: check ready condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckReadyCondition + Last Transition Time: 2024-11-18T14:47:05Z + Message: issuing condition; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IssuingCondition + Last Transition Time: 2024-11-18T14:47:15Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T14:49:40Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T14:47:20Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:47:20Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:48:05Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 Observed Generation: 1 - Reason: CertificateIssuingSuccessful Status: True - Type: CertificateIssuingSuccessful - Last Transition Time: 2021-03-11T16:29:37Z - Message: Successfully Restarted ReplicaSet nodes + Type: CheckPodRunning--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:48:10Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 - Reason: RestartReplicaSet Status: True - Type: RestartReplicaSet - Last Transition Time: 2021-03-11T16:29:37Z - Message: Successfully Reconfigured TLS + Type: GetPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:48:10Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:48:50Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:48:55Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:48:55Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:49:35Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T14:49:40Z + Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal CertificateIssuingSuccessful 2m27s KubeDB Ops-manager operator Successfully Issued New Certificates - Normal RestartReplicaSet 42s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes - Normal Successful 42s KubeDB Ops-manager operator Successfully Reconfigured TLS ``` -Now, Let's exec into a database node and find out the ca subject to see if it matches the one we have provided. +Now, Lets exec into a database node and find out the ca subject to see if it matches the one we have provided. ```bash -$ kubectl exec -it ms-standalone-2 -n demo bash -root@ms o-rs-tls-2:/$ openssl x509 -in /var/run/mssqlserver/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout +$ kubectl exec -it mssql-ag-cluster-2 -n demo -c mssql -- bash +mssql@mssql-ag-cluster-2:/$ openssl x509 -in /var/opt/mssql/tls/ca.crt -inform PEM -subject -nameopt RFC2253 -noout subject=O=kubedb-updated,CN=ca-updated ``` @@ -864,27 +818,27 @@ Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create apiVersion: ops.kubedb.com/v1alpha1 kind: MSSQLServerOpsRequest metadata: - name: mops-remove + name: msops-ag-remove namespace: demo spec: type: ReconfigureTLS databaseRef: - name: ms-standalone + name: mssql-ag-cluster tls: remove: true ``` Here, -- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `ms-standalone` database. +- `spec.databaseRef.name` specifies that we are performing reconfigure TLS operation on `mssql-ag-cluster` database. - `spec.type` specifies that we are performing `ReconfigureTLS` on our database. - `spec.tls.remove` specifies that we want to remove tls from this database. Let's create the `MSSQLServerOpsRequest` CR we have shown above, ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/mops-remove.yaml -mssqlserveropsrequest.ops.kubedb.com/mops-remove created +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/reconfigure-tls/msops-ag-remove.yaml +mssqlserveropsrequest.ops.kubedb.com/msops-ag-remove created ``` #### Verify TLS Removed Successfully @@ -892,134 +846,142 @@ mssqlserveropsrequest.ops.kubedb.com/mops-remove created Let's wait for `MSSQLServerOpsRequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsRequest` CRO, ```bash -$ kubectl get mssqlserveropsrequest -n demo +$ watch kubectl get mssqlserveropsrequest -n demo Every 2.0s: kubectl get mssqlserveropsrequest -n demo -NAME TYPE STATUS AGE -mops-remove ReconfigureTLS Successful 105s +NAME TYPE STATUS AGE +msops-ag-remove ReconfigureTLS Successful 5m17s ``` We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. ```bash -$ kubectl describe mssqlserveropsrequest -n demo mops-remove -Name: mops-remove +$ kubectl describe mssqlserveropsrequest -n demo msops-ag-remove +Name: msops-ag-remove Namespace: demo Labels: Annotations: API Version: ops.kubedb.com/v1alpha1 Kind: MSSQLServerOpsRequest Metadata: - Creation Timestamp: 2021-03-11T16:35:32Z + Creation Timestamp: 2024-11-18T14:56:16Z Generation: 1 - Managed Fields: - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: - .: - f:databaseRef: - .: - f:name: - f:tls: - .: - f:remove: - f:type: - Manager: kubectl-client-side-apply - Operation: Update - Time: 2021-03-11T16:35:32Z - API Version: ops.kubedb.com/v1alpha1 - Fields Type: FieldsV1 - fieldsV1: - f:status: - .: - f:conditions: - f:observedGeneration: - f:phase: - Manager: kubedb-enterprise - Operation: Update - Time: 2021-03-11T16:35:32Z - Resource Version: 525550 - Self Link: /apis/ops.kubedb.com/v1alpha1/namespaces/demo/mssqlserveropsrequests/mops-remove - UID: 99184cc4-1595-4f0f-b8eb-b65c5d0e86a6 + Resource Version: 561471 + UID: 7f43e8b9-4ae9-4f5d-9355-c58a4dbf4504 Spec: + Apply: IfReady Database Ref: - Name: ms-standalone + Name: mssql-ag-cluster Tls: Remove: true Type: ReconfigureTLS Status: Conditions: - Last Transition Time: 2021-03-11T16:35:32Z - Message: MSSQLServer ops request is reconfiguring TLS + Last Transition Time: 2024-11-18T14:56:16Z + Message: MSSQLServer ops-request has started to reconfigure tls for mssqlserver nodes Observed Generation: 1 Reason: ReconfigureTLS Status: True Type: ReconfigureTLS - Last Transition Time: 2021-03-11T16:35:37Z - Message: Successfully Updated PetSets + Last Transition Time: 2024-11-18T14:56:19Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2024-11-18T14:56:24Z + Message: successfully reconciled the MSSQLServer with tls configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2024-11-18T15:01:29Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2024-11-18T14:56:29Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:56:29Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:59:19Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-0 + Last Transition Time: 2024-11-18T14:59:24Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 - Reason: TLSRemoved Status: True - Type: TLSRemoved - Last Transition Time: 2021-03-11T16:37:07Z - Message: Successfully Restarted ReplicaSet nodes + Type: GetPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T14:59:25Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-1 Observed Generation: 1 - Reason: RestartReplicaSet Status: True - Type: RestartReplicaSet - Last Transition Time: 2021-03-11T16:37:07Z - Message: Successfully Reconfigured TLS + Type: EvictPod--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T15:00:09Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-1 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-1 + Last Transition Time: 2024-11-18T15:00:14Z + Message: get pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: GetPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T15:00:14Z + Message: evict pod; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T15:01:24Z + Message: check pod running; ConditionStatus:True; PodName:mssql-ag-cluster-2 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssql-ag-cluster-2 + Last Transition Time: 2024-11-18T15:01:29Z + Message: Successfully completed reconfigureTLS for mssqlserver. Observed Generation: 1 Reason: Successful Status: True Type: Successful Observed Generation: 1 Phase: Successful -Events: - Type Reason Age From Message - ---- ------ ---- ---- ------- - Normal PauseDatabase 2m5s KubeDB Ops-manager operator Pausing MSSQLServer demo/ms-standalone - Normal PauseDatabase 2m5s KubeDB Ops-manager operator Successfully paused MSSQLServer demo/ms-standalone - Normal TLSRemoved 2m5s KubeDB Ops-manager operator Successfully Updated PetSets - Normal RestartReplicaSet 35s KubeDB Ops-manager operator Successfully Restarted ReplicaSet nodes - Normal ResumeDatabase 35s KubeDB Ops-manager operator Resuming MSSQLServer demo/ms-standalone - Normal ResumeDatabase 35s KubeDB Ops-manager operator Successfully resumed MSSQLServer demo/ms-standalone - Normal Successful 35s KubeDB Ops-manager operator Successfully Reconfigured TLS ``` -Now, Let's exec into the database primary node and find out that TLS is disabled or not. +Now, Lets exec into the database node and find out that TLS is disabled or not. ```bash -$ kubectl exec -it -n demo ms-standalone-1 -- mongo admin -u root -p 'U6(h_pYrekLZ2OOd' -rs0:PRIMARY> db.adminCommand({ getParameter:1, sslMode:1 }) -{ - "sslMode" : "disabled", - "ok" : 1, - "$clusterTime" : { - "clusterTime" : Timestamp(1615480817, 1), - "signature" : { - "hash" : BinData(0,"CWJngDTQqDhKXyx7WMFJqqUfvhY="), - "keyId" : NumberLong("6938294279689207810") - } - }, - "operationTime" : Timestamp(1615480817, 1) -} +$ kubectl exec -it -n demo mssql-ag-cluster-1 -c mssql -- bash +mssql@mssql-ag-cluster-1:/$ cat /var/opt/mssql/mssql.conf +[language] +lcid = 1033 +mssql@mssql-ag-cluster-1:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Q9kDWVQMnawLcnZq -N +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : SSL Provider: [error:0A000086:SSL routines::certificate verify failed:self-signed certificate]. +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Client unable to establish connection. + + +So Now, we have to connect with -C [Trust Server Certificate] +mssql@mssql-ag-cluster-1:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P Q9kDWVQMnawLcnZq -N -C +1> ``` So, we can see from the above that, output that tls is disabled successfully. ## Cleaning up -To cleanup the Kubernetes resources created by this tutorial, run: +To clean up the Kubernetes resources created by this tutorial, run: ```bash -kubectl delete mssqlserver -n demo ms-standalone -kubectl delete issuer -n demo ms-issuer ms-new-issuer -kubectl delete mssqlserveropsrequest msops-add-tls mops-remove msops-rotate mops-change-issuer +kubectl delete mssqlserver -n demo mssql-ag-cluster +kubectl delete issuer -n demo mssqlserver-ca-issuer mssqlserver-new-ca-issuer +kubectl delete mssqlserveropsrequest msops-ag-add-tls msops-ag-remove msops-ag-rotate msops-ag-change-issuer kubectl delete ns demo ``` From cde13a8b9db0a0f99b9a22ff22e625532a8133be Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Tue, 19 Nov 2024 12:45:48 +0600 Subject: [PATCH 11/14] Add reconfigure tls image Signed-off-by: Neaj Morshad --- .../mssqlserver/reconfigure-tls/overview.md | 2 +- .../mssqlserver/ms-reconfigure-tls.png | Bin 0 -> 68182 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/images/day-2-operation/mssqlserver/ms-reconfigure-tls.png diff --git a/docs/guides/mssqlserver/reconfigure-tls/overview.md b/docs/guides/mssqlserver/reconfigure-tls/overview.md index fed48c1742..fc62e2e616 100644 --- a/docs/guides/mssqlserver/reconfigure-tls/overview.md +++ b/docs/guides/mssqlserver/reconfigure-tls/overview.md @@ -27,7 +27,7 @@ This guide will give an overview on how KubeDB Ops-manager operator reconfigures The following diagram shows how KubeDB Ops-manager operator reconfigures TLS of a `MSSQLServer` database. Open the image in a new tab to see the enlarged version.
-  Reconfiguring TLS process of MSSQLServer +  Reconfiguring TLS process of MSSQLServer
Fig: Reconfiguring TLS process of MSSQLServer
diff --git a/docs/images/day-2-operation/mssqlserver/ms-reconfigure-tls.png b/docs/images/day-2-operation/mssqlserver/ms-reconfigure-tls.png new file mode 100644 index 0000000000000000000000000000000000000000..090fe28707f08619bd1b9dc9275a6f9f054a010d GIT binary patch literal 68182 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 literal 0 HcmV?d00001 From c206b981cc098323d97a79a1ae903a61d94e0cef Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Tue, 19 Nov 2024 18:50:27 +0600 Subject: [PATCH 12/14] Update concepts Signed-off-by: Neaj Morshad --- .../mssqlserver/concepts/mssqlserver.md | 73 ++++++++++++------- 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/docs/guides/mssqlserver/concepts/mssqlserver.md b/docs/guides/mssqlserver/concepts/mssqlserver.md index 2a9e33f1d0..8f15b42ca6 100644 --- a/docs/guides/mssqlserver/concepts/mssqlserver.md +++ b/docs/guides/mssqlserver/concepts/mssqlserver.md @@ -196,23 +196,7 @@ NAME VERSION DB_IMAGE DE `spec.replicas` specifies the total number of primary and secondary nodes in SQL Server Availability Group cluster configuration. One pod is selected as Primary and others act as secondary replicas. KubeDB uses `PodDisruptionBudget` to ensure that majority of the replicas are available during [voluntary disruptions](https://kubernetes.io/docs/concepts/workloads/pods/disruptions/#voluntary-and-involuntary-disruptions). -To learn more about how to setup a SQL Server Availability Group cluster (HA configuration) in KubeDB, please visit [here](/docs/guides/mssqlserver/clustering/ag_cluster.md). - -### spec.leaderElection - -There are five fields under MSSQLServer CRD's `spec.leaderElection`. These values define how fast the leader election can happen. - -- `Period`: This is the period between each invocation of `Node.Tick`. It represents the time base for election actions. Default is `100ms`. - -- `ElectionTick`: This is the number of `Node.Tick` invocations that must pass between elections. If a follower does not receive any message from the leader during this period, it becomes a candidate and starts an election. It is recommended to set `ElectionTick = 10 * HeartbeatTick` to prevent unnecessary leader switching. Default is `10`. - -- `HeartbeatTick`: This defines the interval between heartbeats sent by the leader to maintain its leadership. A leader sends heartbeat messages every `HeartbeatTick` ticks. Default is `1`. - -- `TransferLeadershipInterval`: This specifies retry interval to transfer leadership to the healthiest node. Default is `1s`. - -- `TransferLeadershipTimeout`: This specifies the retry timeout for transferring leadership to the healthiest node. Default is `60s`. - -You can increase the period and the electionTick if the system has high network latency. +To learn more about how to set up a SQL Server Availability Group cluster (HA configuration) in KubeDB, please visit [here](/docs/guides/mssqlserver/clustering/ag_cluster.md). ### spec.authSecret @@ -273,6 +257,51 @@ MSSQLServer managed by KubeDB can be monitored with Prometheus operator out-of-t `spec.configSecret` is an optional field that allows users to provide custom configuration for MSSQLServer. This field accepts a [`VolumeSource`](https://github.com/kubernetes/api/blob/release-1.11/core/v1/types.go#L47). You can use Kubernetes supported volume source `secret`. +### spec.topology + +The `spec.topology` field specifies the operational mode and configuration of the SQL Server cluster. It defines how the cluster should behave, including the databases that should be included in the setup, and the leader election process for managing the primary-secondary roles. + +#### spec.topology.mode + +The `spec.topology.mode` field determines the mode in which the SQL Server cluster operates. Currently, the supported mode is `AvailabilityGroup`, which configures the cluster as an SQL Server Availability Group (AG). + +- **`AvailabilityGroup` Mode**: + In this mode, the KubeDB operator sets up an Availability Group with one primary replica and multiple secondary replicas for high availability. The databases specified in `spec.topology.availabilityGroup.databases` are automatically created and added to the Availability Group. Users do not need to perform these tasks manually. + +#### spec.topology.availabilityGroup + +The `spec.topology.availabilityGroup` section defines the configuration for SQL Server Availability Group (AG) when the mode is set to `AvailabilityGroup`. It includes details about the databases to be added to the group and the leader election process. + + +##### spec.topology.availabilityGroup.databases + +This field specifies the list of database names to be included in the Availability Group. The KubeDB operator creates and adds these databases to the Availability Group automatically during cluster initialization. Users can modify this list later to add or remove databases as needed. + +Example: + +```yaml +databases: + - agdb1 + - agdb2 +``` +In this example: agdb1 and agdb2 are added to the Availability Group upon cluster setup. + +### spec.topology.availabilityGroup.leaderElection + +There are five fields under MSSQLServer CRD's `spec.leaderElection`. These values define how fast the leader election can happen. + +- `Period`: This is the period between each invocation of `Node.Tick`. It represents the time base for election actions. Default is `100ms`. + +- `ElectionTick`: This is the number of `Node.Tick` invocations that must pass between elections. If a follower does not receive any message from the leader during this period, it becomes a candidate and starts an election. It is recommended to set `ElectionTick = 10 * HeartbeatTick` to prevent unnecessary leader switching. Default is `10`. + +- `HeartbeatTick`: This defines the interval between heartbeats sent by the leader to maintain its leadership. A leader sends heartbeat messages every `HeartbeatTick` ticks. Default is `1`. + +- `TransferLeadershipInterval`: This specifies retry interval to transfer leadership to the healthiest node. Default is `1s`. + +- `TransferLeadershipTimeout`: This specifies the retry timeout for transferring leadership to the healthiest node. Default is `60s`. + +You can increase the period and the electionTick if the system has high network latency. + ### spec.podTemplate KubeDB allows providing a template for database pod through `spec.podTemplate`. KubeDB operator will pass the information provided in `spec.podTemplate` to the PetSet created for MSSQLServer. @@ -379,6 +408,7 @@ The following fields are configurable in the `spec.tls` section: - `alias` represents the identifier of the certificate. It has the following possible value: - `server` is used for server certificate identification. - `client` is used for client certificate identification. + - `endpoint`: For endpoint certificate identification - `exporter` is used for metrics exporter certificate identification. - `secretName` (optional) specifies the k8s secret name that holds the certificates. This field is optional. If the user does not specify this field, the default secret name will be created in the following format: `--cert`. @@ -401,15 +431,6 @@ The following fields are configurable in the `spec.tls` section: - `emailAddresses` (optional) is a list of email Subject Alternative Names to be set in the Certificate. - `privateKey` (optional) specifies options to control private keys used for the Certificate. - `encoding` (optional) is the private key cryptography standards (PKCS) encoding for this certificate's private key to be encoded in. If provided, allowed values are "pkcs1" and "pkcs8" standing for PKCS#1 and PKCS#8, respectively. It defaults to PKCS#1 if not specified. - -### spec.internalAuth -`spec.internalAuth.endpointCert` specifies the TLS/SSL configurations for internal endpoint authentication of sql server availabilty group replicas. An availability group uses TCP endpoints for communication. Under Linux, endpoints for an AG are only supported if certificates are used for authentication. Explore more on [sql server docs](https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-create-availability-group?view=sql-server-ver16&tabs=ru). To generate the certificate used for internal endpoint authentication of availability group replicas, you have to specify - - `issuerRef` is a reference to the `Issuer` or `ClusterIssuer` CR of [cert-manager](https://cert-manager.io/docs/concepts/issuer/) that will be used by `KubeDB` to generate necessary certificates. Same as `spec.tls.issuerRef`. - - `certificates` (optional) is the certificate used to configure endpoints. It has the following fields: - - `alias` represents the identifier of the certificate. It has the following possible value: - - `endpoint` is used for endpoint certificate identification. - - `secretName` (optional) specifies the k8s secret name that holds the certificates. This field is optional. If the user does not specify this field, the default secret name will be created in the following format: `-endpoint-cert`. - - `subject` is same as described in `spec.tls.certificate.subject` ### spec.serviceTemplate From 73c27a813e18ec2458d3c3f4b77caf9b1c7206ed Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Fri, 22 Nov 2024 14:45:23 +0600 Subject: [PATCH 13/14] Update yamls Signed-off-by: Neaj Morshad --- docs/guides/mssqlserver/reconfigure/standalone.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/guides/mssqlserver/reconfigure/standalone.md b/docs/guides/mssqlserver/reconfigure/standalone.md index 72dc0440ec..3a9790a135 100644 --- a/docs/guides/mssqlserver/reconfigure/standalone.md +++ b/docs/guides/mssqlserver/reconfigure/standalone.md @@ -116,6 +116,15 @@ spec: kind: Issuer apiGroup: "cert-manager.io" clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation storageType: Durable storage: storageClassName: "standard" From 26db961f9884df5c32989db1dba6c202ae5b3880 Mon Sep 17 00:00:00 2001 From: Neaj Morshad Date: Fri, 13 Dec 2024 11:16:43 +0600 Subject: [PATCH 14/14] Add review changes Signed-off-by: Neaj Morshad --- .../mssqlserver/ms-update-version.png | Bin 75257 -> 71191 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/images/day-2-operation/mssqlserver/ms-update-version.png b/docs/images/day-2-operation/mssqlserver/ms-update-version.png index 94888b63550b37bf3c14968a6e039911a5b5357f..aceaea669c8d107b8b6b05ab24dce3ca39264c8b 100644 GIT binary patch literal 71191 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 SBa@yo0D-5gpUXO@geCyEI~08Y literal 75257 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