Showing posts with label Kubernetes Service. Show all posts
Showing posts with label Kubernetes Service. Show all posts

Sunday, 25 June 2017

Accessing the Kubernetes API Server From The Pod.

Kubernetes API server can be access from the pod on the following URL, https://kubernetes.default .

To get authenticated for accessing the api server url, we also need to pass the service account token and the "ca cert". Once that is done, we can perform all the operations that are permitted to that service account.

Let's say, suppose we have deployed our code as a POD in the kubernetes cluster, and the same code is responsible for creating other stateful sets /replica sets / services / namespaces. In that case we will required to get authenticated for accessing the api server.  And using kubernetes-client, we can deploy our deployment.


I am using the godaddy-kubernetes-client library for creating namespaces , deployments and statefulsets.

The "token" and "ca cert" resides at the following location in the pod :

a. token : /var/run/secrets/kubernetes.io/serviceaccount/token
b. ca-cert : /var/run/secrets/kubernetes.io/serviceaccount/ca.crt


let getRequestInfo = () => {
    return {
        url: "https://kubernetes.default",
        ca:   fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/ca.crt').toString(),
        auth: {
            bearer: fs.readFileSync('/var/run/secrets/kubernetes.io/serviceaccount/token').toString(),
        },
        timeout: 1500
    };
}

let initK8objs = () =>{
    k8obj = getRequestInfo();
    k8score = new Api.Core(k8obj),
    k8s = new Api.Api(k8obj);
}

And once the authentication is done, we can use the above created k8score and k8s object to perform crud operations on the API server.

ex : k8s.group("v1").ns().post('/json-path')  will create a new namespace.

And the other way of authenticating is passing the cluster username and password with the "ca-cert" also known as basic authentication, In the below case we will need to pass the user and password to the pod by either environment variables or using secrets.

const core = new Api.Core({
  url: 'https://kubernetes.default',
  ca: fs.readFileSync('cluster-ca.pem'),
  auth: {
    user: 'user',
    pass: 'pass'
  }
});

Sunday, 7 May 2017

Kubernetes Service And Their EndPoints.

Its very necessary that we specify a proper selector while creating a kubernetes service. The selectors should be unique. So, that they can easily discover the pods.

If you specify a common selectors for all the services, then it may occur that it will point to a multiple pods. And then it will be very difficult to identify the real cause. I was getting a connection-refused error. Sometimes, when i was accessing pod using a node port service.

In my case i was having two pods (named backend-manager and the other one was named engine).
And i have created two node port services for it (bm and engine).

And here are the service yamls :

1. Engine Service :

"engine": { //Engine /
"apiVersion":"v1",
"kind":"Service",
"metadata":{
"name":"engine",
"namespace":`${tennantId}-${salt}`,
"labels":{
"app":"backend",
"tier":"engine"
}
},
"spec":{
"type":"NodePort",
"selector":{
"app":"backend"
},
"ports":[{
"port":3000,
"targetPort": 3000
}]
}
}


2. BM SERVICE :

"bm": { //Backend Manager
"apiVersion":"v1",
"kind":"Service",
"metadata":{
"name":"bm",
"namespace":`${tennantId}-${salt}`,
"labels":{
"app":"backend",
"tier":"bm"
}
},
"spec":{
"type":"NodePort",
"selector":{
"app":"backend"
},
"ports":[{
"port":3001,
"targetPort": 3001
}]
}
}


As, you can see i have mistakenly mentioned the common selector in both the service.

And lets see, the endpoints for the service, using the below url.

http://localhost:8000/api/v1/namespaces/myapps-fv92n/endpoints/bm

And here is the output :





As, you can clearly see that different pods (both BM and Engine) are listing under the service endpoint (under subsets->addresses highlighted above ). Actually, only BM should be listed.

I have then modified both the service yaml and added one more custom selector:

a. "tier:bm" in BM service.
b. "tier:engine" in Engine Service.

And here is the output for the service endpoint, Only BM is listing under the bm service endpoint.



Sometimes, i was getting the connection refused error while accessing the pods using the node port service. And after updating the service yaml's this issue has been resolved.


Below is the steps for creating the end-point URL :

We can get the endpoints by sending a GET request to the following URL.

The URL contains the following parts :

1. localhost:8000 : As, i have created the proxy (kubectl proxy --port=8000).

2. api/v1 : version

3. namespaces : keyword

4. {{namespace-name}} : Your namespace name, if you have created services under the default namespace, then mentioned it default.

5. endpoints : keyword.

6. {{service-name}} : In my case it is bm

URL :  http://localhost:8000/api/v1/namespaces/myapps-fv92n/endpoints/bm

Sunday, 23 April 2017

Accessing Externally Hosted Mongo-DB inside kuberenetes or minikube

Accessing Externally Hosted Mongo-DB in the Kubernetes/Minikube PODS

We can directly access the externally hosted mongo-db inside the pod, by using it public IP.

But, suppose in future, if the externally hosted mongo dB IP changes, then we would require to update all the pods, that are accessing the database.

The better option is creating a service without selector. So, for it no endpoints will be created. After that we will manually create the endpoints and provide the externally hosted mongodb address there.

In this way, when we access the service, it will automatically route to the end points created for it.

And, if later on if public IP changes for the DB, we will not require to update the pods, just we will require to update the end points.

Below are the json files for it:

  1.   Mongodb Service without Selector:


{
                            "kind": "Service",
                            "apiVersion": "v1",
                            "metadata":{
                                name: "mongodb"
                            },
                            "spec":{
                                "ports":[{
                                    "protocol": "TCP",
                                    "port": 27017,
                                    "targetPort": 27017
                                }]
                            },
                            "selector": {}                  
                }
As you can see, we have not provided any selector for it. So, there will be no end point created for it.
By default the mongo-db is accessible to the default port (27017).

2. End-Point for the above service:

{
                        "kind": "Endpoints",
                        "apiVersion": "v1",
                        "metadata":{
                            "name": "mongodb"
                        },
                        "subsets":[{
                            "addresses":[{
                                "ip": "30.188.60.252",  // This is the external end point.
                                }],
                            "ports":[{
                                "port": 27017,
                                "protocol": "TCP"
                            }]
                        }]
            }

Note : The name property value must match with the newly created service name. That's how both the endpoints and service will associate.



And to access the external mongo-db now, We can just use the service name directly.

Ex :  let constr = "mongodb://abcd:abcd@mongodb";

Or, we can use the service IP also that will proxy the traffic to the endpoint.