<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kevin Summersill</title>
    <description>The latest articles on DEV Community by Kevin Summersill (@ksummersill).</description>
    <link>https://dev.to/ksummersill</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F702866%2F42004731-4116-4631-bf0a-c1b7bdfa91cd.png</url>
      <title>DEV Community: Kevin Summersill</title>
      <link>https://dev.to/ksummersill</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ksummersill"/>
    <language>en</language>
    <item>
      <title>Installing MongoDB on Kubernetes with Replica Sets and NO MongoDB Operator</title>
      <dc:creator>Kevin Summersill</dc:creator>
      <pubDate>Fri, 10 Sep 2021 12:17:04 +0000</pubDate>
      <link>https://dev.to/ksummersill/installing-mongodb-on-kubernetes-with-replica-sets-and-no-mongodb-operator-4bom</link>
      <guid>https://dev.to/ksummersill/installing-mongodb-on-kubernetes-with-replica-sets-and-no-mongodb-operator-4bom</guid>
      <description>&lt;p&gt;Are you tired of searching for MongoDB on Kubernetes and Immediately going to a MongoDB site on how to use their operator? Are you tired of finding nothing but Helm packages that you have no clue what is really going or finding a set of instructions that are made very complex? Are you tired of having no choice but to be pushed to a MongoDB cloud or Cloud Service Provider (AWZ, Azure, and GCP) service? I was tired of looking online just to find some complex way of setting up MongoDB. So let's cut out the complexity and move on to making MongoDB simple.&lt;br&gt;
Shows the full stack deployed on ArgoCD within clusterStep 1. &lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the Role-Based Access Controls (RBAC)
&lt;/h2&gt;

&lt;p&gt;The first thing we need to do is set up a Service Account, a ClusterRole, and connect the two with a Cluster RoleBinding. This will be used for our "headless" service that MongoDB will utilize when creating DNS association of the replica sets.&lt;/p&gt;

&lt;p&gt;Create a file called mongodb-rbac.yml and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: ServiceAccount
metadata:
  name: mongo-account
  namespace: &amp;lt;your-namespace&amp;gt;
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: mongo-role
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["deployments"]
  verbs: ["list", "watch"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mongo_role_binding
subjects:
- kind: ServiceAccount
  name: mongo-account
  namespace: &amp;lt;your-namespace&amp;gt;
roleRef:
  kind: ClusterRole
  name: mongo-role
  apiGroup: rbac.authorization.k8s.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The roles are pretty simple. They are set up to have access to watch and list the deployment and review the services of the pods.&lt;br&gt;
Apply the RBAC by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f mongodb-rbac.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2. Setting up the Headless Service
&lt;/h2&gt;

&lt;p&gt;First of all, What in the world is a "headless" service! Well in Kubernetes by default if no Service Type is specified, then a ClusterIP is given. However, a headless service means that there will be NO ClusterIP given by default. So how do we do this? Well, it's simple. Just add "clusterIP: None" into your specification for the service. Let's do just this.&lt;br&gt;
Create a file called mongodb-headless.yml and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: mongo
  namespace: &amp;lt;your-namespace&amp;gt;
  labels:
    name: mongo
spec:
  ports:
    - port: 27017
      targetPort: 27017
  clusterIP: None
  selector:
    app: mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! Now apply by using;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f mongodb-headless.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3. Setting up the StatefulSet Deployment with Persistence
&lt;/h2&gt;

&lt;p&gt;MongoDB really is Monolithic, but in order to set it up for Kubernetes, a StatefulSet deployment will be required. This is because we will NOT be using an Operator to handle the Statefulness but instead do it on our own. Now there will be Persistance set up as well. This will be done with a VolumeClaimTemplate.&lt;br&gt;
Create a file called mongodb-stateful-deployment.yml and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mongodb-replica
  namespace: &amp;lt;your-namespace&amp;gt;
spec:
  serviceName: mongo
  replicas: 2
  selector:
    matchLabels:
      app: mongo
  template:
    metadata:
      labels:
        app: mongo
        selector: mongo
    spec:
      terminationGracePeriodSeconds: 30
      serviceAccount: mongo-account
      containers:
      - name: mongodb
        image: docker.io/mongo:4.2
        env:
        command: ["/bin/sh"]
        args: ["-c", "mongod --replSet=rs0 --bind_ip_all"]
        resources:
          limits:
            cpu: 1
            memory: 1500Mi
          requests:
            cpu: 1
            memory: 1000Mi
        ports:
        - name: mongo-port
          containerPort: 27017
        volumeMounts:
        - name: mongo-data
          mountPath: /data/db
  volumeClaimTemplates:
  - metadata:
      name: mongo-data
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 20Gi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should be pretty simple to understand. Basically, the Statefulset deployment is using the Service Account that was stood up in Step 1. Then the docker.io/mongo:4.2 image is utilized. The key to the replica set is the commands on runtime in the arg key field. This is what will be used to set up the replica set on runtime for each pod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongod --replSet=rs0 --bind_ip_all
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, the "/data/db" folder is persisted by assigning it to the VolumeClaimTemplate.&lt;br&gt;
Great! Now apply the file by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f mongodb-stateful-deployment.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4. Setting up Replication Host
&lt;/h2&gt;

&lt;p&gt;Some manual configuration will need to be done in order to set up replication. However, the steps are very simple. In order to set up replication, you must first port-forward into Pod 0 that was created by the Statefulset. So let's port-forward by running:&lt;br&gt;
kubectl exec -it mongodb-replica-0 -n  -- mongo&lt;br&gt;
So this will exec an Individual terminal and run the command mongo to access inside of the MongoDB.&lt;br&gt;
From here replication must be initialized. To do so run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rs.initiate()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected output after running rs.initiate() is to see:&lt;br&gt;
"no configuration specified. Using a default configuration for the set".&lt;br&gt;
Now let's set up a variable called cfg. This variable will be used to execute rs.conf(). Run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var cfg = rs.conf()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's utilize the variable to add a Primary server to the ReplicaSet configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cfg.members[0].host="mongodb-replica-0.mongo:27017"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So what in the world does this mean. So the "mongodb-replica-0" represents the Pod Name. The "mongo" represents the "headless service" that we stood up and the 27017 of course is the MongoDB port.&lt;br&gt;
Now lets setup the configuration by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rs.reconfig(cfg)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! What we should now see is a response of:&lt;br&gt;
"ok": 1&lt;br&gt;
The ok of 1 represents that the configuration was successful.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5. Add the Second MongoDB Instance/Pod
&lt;/h2&gt;

&lt;p&gt;Now the second instance/pod needs to be added to the replicaset configuration. To do that run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rs.add("mongodb-replica-0.mongo:27017")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again the output should show an OK status of 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6. Verify the ReplicaSet Status
&lt;/h2&gt;

&lt;p&gt;This is a very easy command and should be used to reference the primary and secondary servers. Run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rs.status()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should now show the two servers added to the replica.&lt;br&gt;
Updating Replicas (Optional)&lt;br&gt;
Now lets say that you want to add another replica set. All you have to do is run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl scale sts &amp;lt;name of statefulset&amp;gt; -n &amp;lt;name of namespace&amp;gt; --replicas &amp;lt;number of replicas&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now to add the replicas to the server just port-forward back into replica-0 pod by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl exec -it mongodb-replica-0 -n &amp;lt;your-namespace&amp;gt; -- mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then repeat what we did in Step 5 but for the new pod added because of the update in replica.&lt;br&gt;
Of course, if you want to remove then just run rs.remove().&lt;br&gt;
Awesome. I will be created an article very soon that will identify how to set up an External Connection within Kubernetes to connect to MongoDB using Compass.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>operations</category>
    </item>
  </channel>
</rss>
