Cannot deploy simple “Hello World” application on Kubernetes Cluster - kubernetes

I have been following this tutorial on creating a hello-world app
https://medium.com/#bhargavshah2011/hello-world-on-kubernetes-cluster-6bec6f4b1bfd
First I create a cluster on gcloud (called hello-world2)
then connect to it locally :
Next I do a git clone of the project listed in the article.
git clone https://github.com/skynet86/hello-world-k8s.git
cd hello-world-k8s/
Inside the directory I find this hello-world.yaml .
It basically lists a deployment and service (I have renamed everything from hello-world to hello-world2)
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world2-deployment
labels:
app: hello-world2
spec:
selector:
matchLabels:
app: hello-world2
replicas: 2
template:
metadata:
labels:
app: hello-world2
spec:
containers:
- name: hello-world2
image: bhargavshah86/kube-test:v0.1
ports:
- containerPort: 80
resources:
limits:
memory: 256Mi
cpu: "250m"
requests:
memory: 128Mi
cpu: "80m"
---
apiVersion: v1
kind: Service
metadata:
name: hello-world2
spec:
selector:
app: hello-world2
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30081
type: NodePort
I apply this file by running :
kubectl create -f hello-world.yaml
Next I run kubectl get all and all my services are nicely listed.
Now, the article claims, I can see my new application by going to this URL : http://localhost:30081.
But I get nothing when I navigate to this link :
What am I doing wrong here?
Also, another question (sorry..). How do I connect this service/deployment to my cluster? is there some kind of cluster apply service command which i need to do? Is my service implicitly already connected?

You need to port-forward the service to your localhost. They most handy way to do this is using https://github.com/txn2/kubefwd. This will batch forward all services in a namespace and even will make the DNS names work locally. Very useful when you debugging 1 service from the IDE locally and everything else stays in the cloud.
Cluster DNS. Every Service objects gets a DNS record inside the cluster DNS server automatically: https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#services. From inside the cluster (other pods), you call your service using service_name.service_namespace.svc.cluster.local:service_port notation.

You can do port-foward use
kubectl port-forward <pod_name> 8080:80
and then go to your browser http://localhost:8080
ABOUT YOUR PROBLEM
Well the link you shared in there application deployed on localhost not on google cloud. So if you want to deploy on google cloud and want to access application in the web browser then you have to create ingress.
But still you can see if your application response, just ssh into one of your VM on kubernetes cluster and do curl http://localhost:30081. because these nodeport are exposed internally and not exposed to outside world that's the reason you can not access it through web browser for that you need some kind of proxy of ingress stuff. I hope these thing clear your understanding

Related

kubernetes apps avalaible on localhost

I have local and dockerized apps which are working excelent on localhost : java backend at 8080, angular at 4200, activemq at 8161, and postgres on 5432
Now,I am trying also to kubernetize apps to make them work on localhosts.
As far as I know kubernetes provides random Ip on clusters, what should I do do make them work on localhosts to listen to each other ? Is there any way to make them automatically start at those localhosts instead of using port forwariding for each service ?
Every service and deployment has similiar structure :
apiVersion: v1
kind: Service
metadata:
name: backend
spec:
selector:
app: backend
type: LoadBalancer
ports:
- protocol: 8080
port: 8080
targetPort: 8080
Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
labels:
app: backend
spec:
replicas: 3
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image:
ports:
- containerPort: 8080
Tried port-forwarding, works, but requires lot of manual work ( open few new powershell windows and then do manual port forwarding)
In the kubernetes eco system apps talk to each other through their services.
If they are in the same namespace they can directly go to the service name of not they need to specify the full name which includes the namespace name:
my-svc.my-namespace.svc.cluster-domain.example
Never mind, find a way to do it automaticaly with port - forwarding, with simply running 1 script
I have wrote a .bat script with these steps:
kubernetes run all deployments file
kubernetes run all services file
15 second timeout to give time to change pod state from pending to running
{ do port forwarding for each service. Every forwarding is in new powershell windows without exiting }

NodePort type service not accessible outside cluster

I am trying to setup a local cluster using minikube in a Windows machine. Following some tutorials in kubernetes.io, I got the following manifest for the cluster:
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-nginx-deployment
labels:
app: external-nginx
spec:
selector:
matchLabels:
app: external-nginx
replicas: 2
template:
metadata:
labels:
app: external-nginx
spec:
containers:
- name: external-nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: expose-nginx
labels:
service: expose-nginx
spec:
type: NodePort
selector:
app: external-nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 32000
If I got things right, this should create a pod with a nginx instance and expose it to the host machine at port 32000.
However, when I run curl http://$(minikube ip):32000, I get a connection refused error.
I ran bash inside the service expose-nginx via kubectl exec svc/expose-nginx -it bash and from there I was able to access the external-nginx pods normally, which lead me to believe it is not a problem within the cluster.
I also tried to change the type of the service to LoadBalancer and enable the minikube tunnel, but got the same result.
Is there something I am missing?
Almost always by default minikube uses docker driver for the minikube VM creation. In the host system it looks like a big docker container for the VM in which other kubernetes components are run as containers as well. Based on tests NodePort for services often doesn't work as it's supposed to like accessing the service exposed via NodePort should work on minikube_IP:NodePort address.
Solutions are:
for local testing use kubectl port-forward to expose service to the local machine (which OP did)
use minikube service command which will expose the service to the host machine. Works in a very similar way as kubectl port-forward.
instead of docker driver use proper virtual machine which will get its own IP address (VirtualBox or hyperv drivers - depends on the system). Reference.
(Not related to minikube) Use built-in feature kubernetes in Docker Desktop for Windows. I've already tested it and service type should be LoadBalancer - it will be exposed to the host machine on localhost.

Deploying Hello World on k8s cluster

I am trying to deploy a "Hello World" application on an EKS cluster I created using eksctl. I have the cluster running with 2 pods and am following a tutorial located at https://shahbhargav.medium.com/hello-world-on-kubernetes-cluster-6bec6f4b1bfd. I created a deployment using the following yaml file:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world-deployment
labels:
app: hello-world
spec:
selector:
matchLabels:
app: hello-world
replicas: 2
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: hello-world
image: bhargavshah86/kube-test:v0.1
ports:
- containerPort: 80
resources:
limits:
memory: 256Mi
cpu: "250m"
requests:
memory: 128Mi
cpu: "80m"
---
apiVersion: v1
kind: Service
metadata:
name: hello-world
spec:
selector:
app: hello-world
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30081
type: NodePort
I then created the deploying by running the following command:
kubectl create -f hello-world.yaml
I am unable to access it on localhost. I believe I am missing a step because the I had created the cluster & deployment on a Linux EC2 instance that I SSH into with Putty and I am accessing localhost on my Windows machine. Any advice how I can connect would be appreciated. Currently I am getting the following when trying to connect to http://localhost:30081/
As you mention, the problem is that you are trying to access to your local machine at port 30081 but the pods that you have created are in your EKS cluster in the cloud. If you want to try out that the application is working you can SSH into the worker node as you have done and use the curl command like this.
curl localhost:30081
That command is going to return the website that you have running in the console (without any format).
I think that in your case the best course will be to use the kubectl port-forward command. This command is going to bind one of your local machine ports into one of the ports of the pods.
Here is the format of the command.
kubectl port-forward POD-NAME-CURRENTLY-RUNNING-IN-CLUSTER UNUSED-PORT-IN-YOUR-PC:APPLICATION-PORT
Here is an example of how to use it and to check out that's working.
kubectl port-forward hello-world-xxxxxx-xxxxx 8000:80
curl localhost:8000
Notice here that I am not using the service port to access the pod. This tool is great for debugging!
Another approach could be to open port 30081 with a security group and hit the IPs of the worker nodes but I think that's insecure and also have a lot of extra steps. You should check out the difference between type of services.
Let me know if you have any doubts about my answer. I am not an expert and I could be wrong!
Also English is not my first language.
Cheers

How to access app once deployed via Kubernetes?

I have a very simple Python app that works fine when I execute uvicorn main:app --reload. When I go to http://127.0.0.1:8000 on my machine, I'm able to interact with the API. (My app has no frontend, it is just an API built with FastAPI). However, I am trying to deploy this via Kubernetes, but am not sure how I can access/interact with my API.
Here is my deployment.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16.1
ports:
- containerPort: 80
When I enter kubectl describe deployments my-deployment in the terminal, I get back a print out of the deployment, the namespace it is in, the pod template, a list of events, etc. So, I am pretty sure it is properly deployed.
How can I access the application? What would the url be? I have tried a variety of localhost + port combinations to no avail. I am new to kubernetes so I'm trying to understand how this works.
Update:
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-deployment
namespace: default
spec:
selector:
matchLabels:
app: web
replicas: 2
template:
metadata:
labels:
app: web
spec:
containers:
- name: site
image: nginx:1.16.1
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: app-entrypoint
namespace: default
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 30001
Again, when I use the k8s CLI, I'm able to see my deployment, yet when I hit localhost:30001, I get an Unable to connect message.
You have given containerPort: 80 but if your app listens on port 8080 change it to 8080.
There are different ways to access an application deployed on kubernetes
Port Forward using kubectl port-forward deployment/my-deployment 8080:8080
Creare a NodePort service and use http://<NODEIP>:<NODEPORT>
Create a LoadBalanceer service. This works only in supported cloud environment such as AWS, GKE etc.
Use ingress controller such nginx to expose the application.
By Default k8s application are exposed only within the cluster, if you want to access it from outside of the cluster then you can select any of the below options:
Expose Deployment as a node port service (kubectl expose deployment my-deployment --name=my-deployment-service --type=NodePort), describe the service and get the node port assigned to it (kubectl describe svc my-deployment-service). Then try http://<node-IP:node-port>/
For production grade cluster the best practice is to use LoadBalancer type (kubectl expose deployment my-deployment --name=my-deployment-service --type=LoadBalancer --target-port=8080) as part of this service you get an external IP which can be used to access your service http://EXTERNAL-IP:8080/
You can also see the details about the endpoint using kubectl get ep
Thanks,

How do I publish .NET Core to Digital Ocean Kubernetes

I am trying to publish a .NET Core Web App and a .NET Core API.
I have been googling and can't find a way to deploy 1 let alone 2 .NET Core apps to a Digital Ocean Kubernetes Cluster, I have 2 nodes and have created a valid manifest and build a Docker image locally and it seems to pass the validation. But I can't actually deploy it. I'm new to Kubernetes and anything I find seems to be related to Google's Kubernetes or Azure Kubernetes.
I don't, unfortunately, have more information than this.
I have one. Weird thing is that DO is actually smart to not have docs
since it doesn't have to. You can recycle Google's and Azure's K8
documentation to work on your DO cluster. The key difference is only
in the namings I suppose, there could be more differentiations but so
far, I haven't met a single problem while applying instructions from
GCP's docs.
https://nozomi.one is running on DO's k8 cluster.
Here's an awesome-dotnetcore-digitalocean-k8 for you.
Errors you may/will face:
Kubernetes - Error message ImagePullBackOff when deploy a pod
Utilising .NET Core appsettings in docker k8
Push the secret file here (Recommended only for staging or below, unless you have a super secret way to deploy this):
kubectl create secret generic secret-appsettings --from-file=./appsettings.secrets.json
And then create a deployment configuration similar to this. Notice that we've added the appsettings at the last few lines:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: xxxxx
spec:
replicas: 3
template:
metadata:
labels:
app: xxxxx
spec:
containers:
- name: xxxxx
image: xxxxx/xxxxxx:latest
ports:
- containerPort: 80
env:
- name: "ASPNETCORE_ENVIRONMENT"
value: "Production"
volumeMounts:
- name: secrets
mountPath: /app/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: secret-appsettings
Deploying this script is as simple as:
kubectl create -f deployment.yaml
And if you want to test locally in docker first:
docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/test-app:v1
All in all, everything above will help you to deploy your pods.
You need to understand that deploying a new project/app works in this systematic way:
Create a deployment, which is something that pulls the image for you and creates pods that will be deployed to the nodes.
Create a service, that will point proper ports and more (Never tried to do more lol) to your app/s.
This is how a service looks like:
apiVersion: v1
kind: Service
metadata:
name: nozweb
spec:
type: LoadBalancer
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80
- name: https
port: 443
protocol: TCP
targetPort: 80
selector:
app: nozweb
Always ensure that spec:selector:app is specifically following:
spec:
replicas: 3
template:
metadata:
labels:
app: xxxxx
In your deployment configuration. That's how they symlink.
Create an ingress (Optional) that will help act as a reverse proxy to your .NET Core app/project. This is optional because we got kestrel running!