I'm building a K8 cluster for a school project.
It's bare metal and uses metallb as a loadbalancer.
Each service works in a separate pod:
Nginx
Wordpress
Phpmyadmin
Mysql (mariadb)
In the phpmyadmin file, I need to link my mysql server with something like this:
$cfg['Servers'][$i]['host'] = "mysql-server-name";
I've tried to use the node's IP:
kubectl get node -o=custom-columns='DATA:status.addresses[0].address' | sed -n 2p
adding the port :3306 but I realised that none of my services could be reached through the browser with this method.
For instance the node's Ip:5050 should redirect me to my wordpress but it doesn't.
Is there any way to get a single IP that I can use to make my pods communicate between them ?
I must add that each service works appart when I use the svc IP instead of the nodes.
Here's the configmap I use for metallb:
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.99.100-192.168.99.200
The reason the node IP doesn't expose your application to other apps is that the pods in the kubernetes cluster don't listen to the requests coming to the node by default. In other words, the port on the pod is not connected to the port on the node.
The service resource is what you need to make that connection.
Services have different types. A service of type cluster IP will assign an IP internal to the cluster to the app. If you don't want to access your mysql database directly from the internet, this is what you would want.
Here is an example service of type cluster IP for your project.
apiVersion: v1
kind: Service
metadata:
name: mysql-service
namespace: metallb-system
spec:
selector:
app: Mysql
ports:
- protocol: TCP
port: 80
targetPort: 3306
Selector selects pods that carry the label app=mysql.
Port is the port that the service will listen to.
TargetPort is the port that mysql is listening to.
When you create the service you can find it's IP by running this command
kubectl get services -n metallb-system
Under CLUSTER-IP column note the IP of the service you created.
So in this case, if mysql is listening to 3306, you can reach it through this service on the service IP on port 80.
If you want to expose your wordpress app to the internet, use either the NodePort or LoadBalancer service types. Here is the reference for service types.
Related
I know a scenario of kubernetes headless service with selector.
But what’s the usage scenario of kubernetes headless service without selector?
Aliasing external services into the cluster DNS.
Services without selectors are used if you want to have an external database cluster in production, but in your test environment you use your own databases, to point your Service to a Service in a different Namespace or on another cluster, when you are migrating a workload to Kubernetes.
Service without selectors are often used to alias external services into the cluster DNS.
Here ia an example of service without selector:
apiVersion: v1
kind: Service
metadata:
name: example-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
This Service has no selector, the corresponding Endpoint object is not created automatically. You can manually map the Service to the network address and port where it’s running, by adding an Endpoint object manually:
apiVersion: v1
kind: Endpoints
metadata:
name: example-service
subsets:
- addresses:
- ip: 192.0.2.42
ports:
- port: 9376
If you have more that one IP address for redundancy, you can repeat them in the addresses array. Once the endpoints are populated, the load balancer will start redirecting traffic from your Kubernetes service to the IP addresses,
Note: The endpoint IPs must not be: loopback (127.0.0.0/8 for IPv4, ::1/128 for IPv6), or link-local (169.254.0.0/16 and 224.0.0.0/24 for IPv4, fe80::/64 for IPv6). Endpoint IP addresses cannot be the cluster IPs of other Kubernetes Services, because kube-proxy doesn’t support virtual IPs as a destination.
You can access a Service without a selector the same as if it had a selector.
Take a look: services-without-selector, example-service-without-selector.
Is it possible to map Kubernetes service to a specific port for a group of pods (deployement)?
E.g. I have service (just as an example)
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 8081
targetPort: 8081
And I want this service be available as http://localhost:8081/ in my pods from some specific deployment.
It seems to me that I saw this in K8S docs several days ago, but I can not find this right now.
It may be beneficial to review your usage of K8s services. If you had exposed a deployment of pods as a service, then your service will define the port mappings, and you will be able to access your service on its cluster DNS name on the service port.
If you must access your service via localhost, I am assuming your use case is some tightly coupled containers in your pod. In which case, you can define a "containerPort" in your deployment yaml, and add the containers that need to communicate with each other on localhost in the same pod.
If by localhost you are referring to your own local development computer, you can do a port-forward. As long as the port-forwarding process is running, you can access the pods' ports from your localhost. Find more on port-forwarding. Simple example:
kubectl port-forward redis-master-765d459796-258hz 6379:6379
# or
kubectl port-forward service/redis 6379:6379
Hope this helps!
i have a application ( Let's say Integration-protocol-api)
and this application want to talk to other application, but this application located on another Network (Let's call it Another-Integration-Protocol)
And problem is, on another-integration-protocol side the whitelist exist, which allow to connect to it, only from selected ip addresses.
But my integration-protocol-api is Dockerized and running on Kubernetes cluster, so ip address is changing everyime when i restart my pod.
how can i assign the Public and Static ip to my Kubernetes Pod?
But my integration-protocol-api is Dockerized and running on Kubernetes cluster, so ip address is changing everyime when i restart my pod. how can i assign the Public and Static ip to my Kubernetes Pod
There are several approaches, depending on your actual setup/needs and I'll try to give some options here:
Tie pod to specific node and expose that node's IP address through service. This would be something along those lines:
# Quick deployment/pod manifest node selector (affinity is better)
...
spec:
nodeSelector:
kubernetes.io/hostname: my-node-name
...
# Service manifest
apiVersion: v1
kind: Service
metadata:
name: svc-myservice
labels:
app: myapp
tier: frontend
spec:
selector:
app: myapp
tier: frontend
ports:
- name: tcpserviceport
protocol: TCP
port: 8080
targetPort: 80
externalIPs:
- 111.222.222.111
Pod should be in same namespace, tied to that node via either node selector or affinity rules and have same labels as in selector for service to pick it up. IP address of cluster node with name my-node-name should be 111.222.222.111 in this example, and it would be accessible through port 8080 and that ip address.
If applicable, expose service through ingress and whitelist ingress public ip only. Depending on your namespace separation you'll reference your pod (wherever it might run) in ingress through corresponding service using either service name (in namespace scope) or FQDN such as:
<service-name>.<namespace-name>.svc.cluster.local
Here is good overview of some methods to make it more illustrative from kubernetes docs: https://kubernetes.io/docs/tutorials/kubernetes-basics/expose-intro/
A pod makes any request with it's node IP address as source. So you could whitelist your cluster nodes' IP addresses, and it should work.
I've installed minikube to learn kubernetes a bit better.
I've deployed some apps and services which have ip's in a range of 10.x.x.x (private ip). I can expose my services on minikube and visit them in my browser. But I want to use the private IP's and not exposing it.
How can I visit (vpn/proxy wize) private ip's of services in minikube?
Minikube is Kubernetes with only one node and master server running on this node.
It provides the possibility to learn how it works with minimum hardware required.
It's ideal for testing purposes and seamless running on a laptop. Minikube is still software with mature
network stack from Kubernetes. This means that ports are exposed to services and virtually services are
communicating with pods.
To understand what is communicating, let me explain what ClusterIP does - it exposes the service on an internal IP in the cluster. This type makes service only reachable from within the cluster.
Cluster IP you can get by the command:
kubectl get services test_service
So, after you create a new service, you like to establish connections to ClusterAPI.
Basically, there are three ways to connect to backend resource:
1/ use kube-proxy - this proxy reflects services as defined in the Kubernetes API and simple stream TCP and UDP to backend or set of them in advanced configuration. Service cluster IPs and ports are currently found through Docker compatible environment variables specifying ports opened by the service proxy. There is an optional addon that provides cluster DNS for these cluster IPs. The user must create a service with the apiserver API to configure the proxy.
Example shows how can we use nodeselectors to define connection to port 5000 on ClusterIP - config.yaml may consist of:
kind: Service
apiVersion: v1
metadata:
name: jenkins-discovery
namespace: ci spec:
type: ClusterIP
selector:
app: master
ports:
- protocol: TCP
port: 50000
targetPort: 50000
name: slaves
2/ use port forwarding to access application - first check if kubectl command-line tool to communicate with your minikube cluster works, then if true find service port from ClusterIP configuration.
kubectl get svc | grep test_service
Let assume service test_service works on port 5555 so to do port forwarding run the command:
kubectl port-forward pods/test_service 5555:5555
After that, you service will be available on the localhost:5555
3/ If you are familiar with the concept of pods networking you cat declare public ports in the pod’s manifest file. A user can connect to pods network defining manifest:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 8080
When the container is starting with manifest file like above host port TCP port 8080 will be forwarded to pod port 8080.
Please keep in the mind that ClusterIP is the use of a lot of services regarding to proper works of the cluster. I think it is not good practice to deal with ClusterIP as a regular network service - on worst scenario, it breaks a cluster soon, by invalid internal network state of connections.
I'm running a bare metal Kubernetes cluster and trying to use a Load Balancer to expose my services. I know typically that the Load Balancer is a function of the underlying public cloud, but with recent support for Ingress Controllers it seems like it should now be possible to use nginx as a self-hosted load balancer.
So far, i've been following the example here to set up an nginx Ingress Controller and some test services behind it. However, I am unable to follow Step 6 which displays the external IP for the node that the load balancer is running on as my node does not have an ExternalIP in the addresses section, only a LegacyHostIP and InternalIP.
I've tried manually assigning an ExternalIP to my cluster by specifying it in the service's specification. However, this appears to be mapped as the externalID instead.
How can I manually set my node's ExternalIP address?
This is something that is tested and works for an nginx service created on a particular node.
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
name: http
- port: 443
protocol: TCP
targetPort: 443
name: https
externalIPs:
- '{{external_ip}}'
selector:
app: nginx
Assumes an nginx deployment upstream listening on port 80, 443.
The externalIP is the public IP of the node.
I would suggest checking out MetalLB: https://github.com/google/metallb
It allows for externalIP addresses in a baremetal cluster using either ARP or BGP. It has worked great for us and allows you to simply request a LoadBalancer service like you would in the cloud.