I am trying to deploy a jupyter notebook from Kubernetes; however, when I start jupyter and it prints a local host link, I am unable to open it on my computer because it's a "local host." Hence, it needs to be opened within the container.
However, I was unable to find any type of GUI desktop for kubernetes and I'm unsure how to open a browser to fire up the link. I saw some things about minikube. Is there a way to do this without using minikube?
The reason I am trying to install without minikube is because minikube requires hyper V and I have Windows 10 Home which is not compatible with hyper V.
The most common way to access an application in a pod is to use Service.
After creation, a Service object is assigned with a unique IP address (ClusterIP) which remains the same during the whole lifespan of the Service object. Pods can use this ClusterIP and port to access a subset of pods with labels matched to Service selector. When several pods are matched, Service chooses one of them as a destination by round-robin principle.
For example:
You can create a Service for your 2 nginx replicas with kubectl expose:
$ kubectl expose deployment/my-nginx
service "my-nginx" exposed
This is equivalent to kubectl create -f nginx-svc.yaml
with nginx-svc.yaml content as:
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: my-nginx
How to check your Service:
$ kubectl get svc my-nginx
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx 10.0.162.149 <none> 80/TCP 21s
In some parts of your applications, you may want to expose Service onto an external IP address. Kubernetes supports two ways of doing this: NodePorts and LoadBalancers.
NodePort mode reserves one port on all cluster nodes and forwards traffic coming to this port to the pod which is matched to the selector.
In LoadBalancer mode, Service creates cloud load balancer and forwards traffic from the load balancer to the pod which is matched to the selector.
You can read more about it in the document Connecting Applications with Services
To avoid creating all these objects manually, you can use helm to generate and run objects based on a template for a particular application. Here is helm repository for jupiter notebook:
https://github.com/UNINETT/helm-charts
Kubernetes has WebUI called Dashboard. It doesn´t deploy by default, but it´s easy to deploy when you need it.
To deploy Dashboard, execute the following command:
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
To access Dashboard from your local workstation, you must create a secure channel to your Kubernetes cluster. Run the following command:
$ kubectl proxy
Now access Dashboard at:
http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/.
To find out how to create sample user and log in, follow Creating sample user guide.
Since version 1.7 Dashboard by default has a minimal set of privileges and can only be accessed over HTTPS. Access Control guide can help you to extend user permissions.
In case you are limited with OS version, you can use free Oracle VirtualBox for minikube.
Related
When deploying container in kube-system you can see the fqdn of masternode api being used.
When creating a namespace and deploy same container it is kubernetes service with internal ip for the KUBERNETES_SERVICE_HOST environment variable.
We cannot use kind: PodPreset in AKS so i don't know any other way on how to set this environment variable for new pods.
Pods are being deploying with helm in this namespace so you can't set this environment variable in a way that helm will use this in deployment.
The Kubernetes Container Environment provides several important resources to Containers, one of them is:
A list of all services that were running when a Container was created is available to that Container as environment variables. Those environment variables match the syntax of Docker links.
For a service named foo that maps to a Container named bar, the following variables are defined:
FOO_SERVICE_HOST=0.0.0.0 (The IP Address of the service foo)
FOO_SERVICE_PORT=65535 (the port of the service foo)
XXX_SERVICE_PORT is generated automatically based on the services available for the container at the moment of it's creation.
When deploying container in kube-system you can see the fqdn of masternode api being used. When creating a namespace and deploy same container it is kubernetes service with internal ip for the KUBERNETES_SERVICE_HOST environment variable.
It should work both ways because the kubernetes.default service is a relay agent to the master API, take a look at the description of the service:
$ k describe svc kubernetes
Name: kubernetes
Namespace: default
Labels: component=apiserver
provider=kubernetes
Annotations: <none>
Selector: <none>
Type: ClusterIP
IP: 10.21.0.1
Port: https 443/TCP
TargetPort: 443/TCP
Endpoints: 10.54.240.1:443
Session Affinity: None
Events: <none>
$ kubectl cluster-info
Kubernetes master is running at https://10.54.240.1
The endpoint of the kubernetes.default service is the master API IP, so if your deployment is not working as intended, it might have another issue under the hood.
You can also follow the instructions given in #djsly answer and open an issue on the prom-op github, vote for podPreset to become available on AKS or even experiment with other cloud providers (like GCP that offers a free tier so you can try out).
If you have any further questions let us know.
PodPreset is indeed not yet supported on AKS.
I would suggest that you vote on the following feedback: https://feedback.azure.com/forums/914020-azure-kubernetes-service-aks/suggestions/35054089-support-podpreset-alpha-feature
Right now, I would say the only way would be to augment the prometheus-operator chart with support for updating the ENV on the pods you need to overwrite. Pull Requests on Charts are often accepted quite fast.
https://github.com/helm/charts/tree/master/stable/prometheus-operator
or on any of the requirements defined in the chart that you think is missing the support.
I got the following service defined:
apiVersion: v1
kind: Service
metadata:
name: customerservice
spec:
type: NodePort
selector:
app: customerapp
ports:
- protocol: TCP
port: 31004
nodePort: 31004
targetPort: 8080
Current situation: I am able to hit the pod via the service IP.
Now my goal is to reach the customerservice via the name of the service, which does not work right now. So I would simply type http://customerservice:31004 instead of http://<IP>:31004.
DNS resolution of services is ONLY available within the cluster, provided by CoreDNS/KubeDNS.
Should you wish to have access to this locally on your machine, you'd need to use another tool. One such tool is kubefwd:
https://github.com/txn2/kubefwd
A slightly simpler solution, is to use port-forward; which is a very simple way to access a single service locally.
kubectl port-forward --namespace=whatever svs/service-name port
EDIT:// I've made the assumption that you want to use the service DNS locally, as I'm assuming by saying:
I would simply type http://customerservice:31004
is in the context of your web browser.
Normal Services are assigned a DNS A record for a name of the form my-svc.my-namespace.svc.cluster.local. This resolves to the cluster IP of the Service. This DNS entry is present inside the kubernetes cluster only and hence you're able to access the service by name from inside the kubernetes pod.
Now, if you want to access your kubernetes service by name from one of the node you need to modify the /etc/resolve.conf of your node with <svc_name>.<namespace>.svc.cluster.local, please have a look at following /etc/resolve.conf
search ec2.internal default.svc.cluster.local svc.cluster.local cluster.local
nameserver 10.96.0.10
nameserver is clusterIP of kube-dns service, you can find it using kubectl get svc kube-dns -n kube-system
Now you will be able to curl your service as curl ui.default.svc.cluster.local:80
There are various answers for very similar questions around SO that all show what I expect my deployment to look like, however mine does not.
I am running Minikube 0.25, with Kubernetes 1.9 on Windows
10.
I have successfully created a node, a replication controller, and a
single pod template has been replicated 10 times.
The node is Minikube, and is assigned the IP address 10.49.106.251
The dashboard is available at 10.49.106.251:30000
I am deploying a service with a YAML file, but the service is never assigned an external IP - the result is the same if I happen to use kubectl expose.
The YAML file that I am using:
kind: Service
apiVersion: v1
metadata:
name: hello-service
spec:
type: NodePort
selector:
app: hello-world
ports:
- protocol: TCP
port: 8080
I can also use the YAML file to assign an external IP - I assign it the same value as the node IP address. Either way results in no possible connection to the service. I should also point out that the 10 replicated pods all match the selector.
The result of running kubectl get svc for the default, and after updating the external IP are below:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-service NodePort 10.108.61.233 <none> 8080:32406/TCP 1m
hello-service NodePort 10.108.61.233 10.49.106.251 8080:32406/TCP 1m
The tutorial I have been following, and the other answers on SO show a result similar to:
hello-service NodePort 10.108.61.233 <nodes> 8080:32406/TCP 1m
Where the difference is that the external IP is set to <nodes>
I have encountered a number of issues when running locally - is this just another case of doing so, or has someone else identified a way to get around the external IP assignment issue?
For local development purpose, I have also met with the problem of exposing a 'public IP' for my local development cluster.
Fortunately, I have found one of the kubectl command which can help:
kubectl port-forward service/service-name 9092
Where 9092 is the container port to expose, so that I can access applications inside the cluster, on my local development environment.
The important note is that it is not a 'production' grade solution.
Works well as a temporary hack to get to the cluster insides.
Using NodePort means it will open a port on all nodes of your cluster. In your example above, the port exposed to the outside world is 32406.
In order to access hello-service (if it is http) it will be http://[ the node ip]:32406/. This will hit your minikube and the the request will be routed to your pod in roundrobin fashion.
same problem when trying to deploy a simple helloworld image locally with Kubernetes v1.9.2
After two weeks of attempts , It seems that Kubernetes expose all nginx web server applications internally in port 80 not 8080
So this should work kubectl expose deployment hello-service --type=NodePort --port=80
I've setup a NodePort service using the following config:
wordpress-service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: wordpress
name: wordpress
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: wordpress
Is this sufficient to access the service externally, if so how can I now access the service? What details do I need - and how do I determine them - for example node IP.
For Kubernetes on GCE:
We had the same question regarding services of type NodePort: How do we access node port services from our own host?
#ivan.sim 's answer (nodeIp:nodePort) is on mark however, you still wouldn't be able to access your service unless you add a firewall ingress (inbound to google cloud) traffic rule on the VPC network console to allow your host to be able to access your compute node
the above rule is dangerous and should be used only during development
You can find the node port using either the Google Cloud console or by running subsequent kubectl commands to find out the node running your pod which has your container. i.e kubectl get pods , kubectl describe pod your-pod-name, kubectl describe node node-that-runs-you-pod .status.addresses has your ExternalIP
It would be great if we could extract the node ip running our container in the pod using only a label/selector and a few line of commands, so here is what we did, in this case our selector is app: your-label:
$ nodename=$(kubectl get pods -o jsonpath='{.items[?(#.metadata.labels.app=="your-label")].spec.nodeName}')
$ nodeIp=$(kubectl get nodes -o jsonpath='{.items[?(#.metadata.name=="'$(echo $nodename)'")].status.addresses[?(#.type=="ExternalIP")].address}')
$ echo nodeIp
notice: we used json path to extract the information we desired, for more on json path see: json path
You could certainly turn this into a script that takes a label/selector as input and outputs an external ip of the node running your container !!!
To get the nodeport just type:
$ kubectl get services
under the PORT(S) columns you will see something like tagetPort:nodePort. this nodeport is what you want .
nodeIp:nodePort
When you define a service as type NodePort, every node in your cluster will proxy that port to your service. If you nodes are reachable from outside the Kubernetes cluster, you should be able to access the service at nodeIP:nodePort.
To determine nodeIP of a particular node, you can use either kubectl get no <node> -o yaml or kubectl describe no <node>. The status.Addresses field will be of interest. Generally, you will see fields like HostName, ExternalIP and InternalIP there.
To determine nodePort of your service, you can use either kubectl get svc wordpress -o yaml or kubectl describe svc wordpress. The spec.ports.nodePort is the port you need.
Service defined like this got assgned a high port number and is exposed on all your cluster nodes on that port (probably something like 3xxxx). Hard to tell the rest without proper knowledge of how your cluster is provisioned. kubectl get nodes should give you some knowledge about your nodes.
Although I assume you want to expose the service to the outside world. In the long run I suggest getting familiar with LoadBalancer type services and Ingress / IngressController
I run the CoreOS k8s cluster on Mac OSX, which means it's running inside VirtualBox + Vagrant
I have in my service.yaml file:
spec:
type: NodePort
When I type:
kubectl get services
I see:
NAME CLUSTER_IP EXTERNAL_IP PORT(S) SELECTOR
kubernetes 10.100.0.1 <none> 443/TCP <none>
my-frontend 10.100.250.90 nodes 8000/TCP name=my-app
What is the "nodes" external IP? How do I access my-frontend externally?
In addition to "NodePort" types of services there are some additional ways to be able to interact with kubernetes services from outside of cluster:
Use service type "LoadBalancer". It works only for some cloud providers and will not work for virtualbox, but I think it will be good to know about that feature. Link to the documentation
Use one of the latest features called "ingress". Here is description from manual "An Ingress is a collection of rules that allow inbound connections to reach the cluster services. It can be configured to give services externally-reachable urls, load balance traffic, terminate SSL, offer name based virtual hosting etc.". Link to the documentation
If kubernetes is not strict requirements and you can switch to latest openshift origin (which is "kubernetes on steroids") you can use origin feature called "router".
Information about openshift origin.
Information about openshift origin routes
I assume you are using MiniKube for Kubernetes. In such case, to identify your node ip address, use the following command:
.\minikube.exe ip
If the exposed service is of type=Nodeport, to check the exposed port use the following command:
.\kubectl.exe describe service <service-name>
Check for Node port in the result. Also, if you want to have all these details via nice UI, then you can launch the Kubernetes Dashboard present at the following address:
<Node-ip>:30000
The easiest way to get the host ports is kubectl describe services my-frontend.
The node port will be displayed.
Also you can check the api:
api/v1/namespaces/{namespace_name}/services/{service_name}
or list all:
api/v1/namespaces/default/services
Last, you can chose a fixed nodePort in the service.yml
Here is the doc on node addresses: http://kubernetes.io/docs/admin/node/#addresses
You can specify the port number of nodePort when you specify the service. If you didn't manually specify a port, system will allocate one for you. You can kubectl get services -o yaml and find the port at spec.ports[*].nodePort, as suggested in the doc here: https://github.com/kubernetes/kubernetes/blob/master/docs/user-guide/services.md#type-nodeport
And you can access your front-end at {nodes' external addresses}:{nodePort}
Hope this helps.