I am trying to set up a generic pod on OpenShift 4 that can connect to a mysql server running on a separate VM outside the OpenShift cluster (testing using local openshift crc). However when creating the deployment, I'm unable to connect to the mysql server from inside the pod (for testing purposes).
The following is the deployment that I use:
kind: "Service"
apiVersion: "v1"
metadata:
name: "mysql"
spec:
ports:
- name: "mysql"
protocol: "TCP"
port: 3306
targetPort: 3306
nodePort: 0
selector: {}
---
kind: "Endpoints"
apiVersion: "v1"
metadata:
name: "mysql"
subsets:
- addresses:
- ip: "***ip of host with mysql database on it***"
ports:
- port: 3306
name: "mysql"
---
apiVersion: v1
kind: DeploymentConfig
metadata:
name: "deployment"
spec:
template:
metadata:
labels:
name: "mysql"
spec:
containers:
- name: "test-mysql"
image: "***image repo with docker image that has mysql package installed***"
ports:
- containerPort: 3306
protocol: "TCP"
env:
- name: "MYSQL_USER"
value: "user"
- name: "MYSQL_PASSWORD"
value: "******"
- name: "MYSQL_DATABASE"
value: "mysql_db"
- name: "MYSQL_HOST"
value: "***ip of host with mysql database on it***"
- name: "MYSQL_PORT"
value: "3306"
I'm just using a generic image for testing purposes that has standard packages installed (net-tools, openjdk, etc.)
I'm testing by going into the deployed pod via the command:
$ oc rsh {{ deployed pod name }}
however when I try to run the following command, I cannot connect to the server running mysql-server
$ mysql --host **hostname** --port 3306 -u user -p
I get this error:
ERROR 2003 (HY000): Can't connect to MySQL server on '**hostname**:3306' (111)
I've also tried to create a route from the service and point to that as a "fqdn" alternative but still no luck.
If I try to ping the host (when inside the pod), I cannot reach it either. But I can reach the host from outside the pod, and from inside the pod, I can ping sites like google.com or github.com
For reference, the image being used is essentially the following dockerfile
FROM ubi:8.0
RUN dnf install -y python3 \
wget \
java-1.8.0-openjdk \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \
postgresql-devel
WORKDIR /tmp
RUN wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm && \
rpm -ivh mysql-community-release-el7-5.noarch.rpm && \
dnf update -y && \
dnf install mysql -y && \
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.48.tar.gz && \
tar zxvf mysql-connector-java-5.1.48.tar.gz && \
mkdir -p /usr/share/java/ && \
cp mysql-connector-java-5.1.48/mysql-connector-java-5.1.48-bin.jar /usr/share/java/mysql-connector-java.jar
RUN dnf install -y tcping \
iputils \
net-tools
I imagine there is something I am fundamentally misunderstanding about connecting to an external database from inside OpenShift, and/or my deployment configs need some adjustment somewhere. Any help would be greatly appreciated.
As mentioned in the conversation for the post, it looks to be a firewall issue. I've tested again with the same config, but instead of an external mysql db, I've tested via deploying mysql in openshift as well and the pods can connect. Since I don't have control of the firewall in the organisation, and the config didn't change between the two deployments, I'll mark this as solved as there isn't much more I can do to test it
Related
Here we have a sample of the job
apiVersion: batch/v1
kind: Job
metadata:
# Unique key of the Job instance
name: example-job
spec:
template:
metadata:
name: example-job
spec:
containers:
- name: pi
image: perl
command: ["perl"]
args: ["-Mbignum=bpi", "-wle", "print bpi(2000)"]
# Do not restart containers after they exit
restartPolicy: Never
I want to run a MySQL script as a command:
mysql -hlocalhost -u1234 -p1234 --database=customer < script.sql
But Kubernetes documentation is silent about piping a file to stdin. How can I specify that in Kubernetes job config?
Would set your command to something like [bash, -c, "mysql -hlocalhost -u1234 -p1234 --database=customer < script.sql"], since input redirection like that is actually a feature of your shell.
I have created mysql k8s container and nodejs k8s container under same namespace.I can't able to connect mysql db.(sequalize)
I have tried to connect using '''http://mysql.e-commerce.svc.cluster.local:3306'''.But i got "SequelizeHostNotFoundError" error.
Here is my service and deployment yaml files.
kind: Service
metadata:
labels:
app: mysql
name: mysql
namespace: e-commerce
spec:
type: NodePort
ports:
- port: 3306
targetPort: 3306
nodePort: 30306
selector:
app: mysql
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: mysql
namespace: e-commerce
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- image: mysql:5.6
name: mysql-container
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim```
From the ClusterIP worked for me or better way to go with the host name of the local cluster service ex. db-mysql.default.svc.cluster.local. This way if you cluster restarts and your IP changes, then you got it covered.
You are trying to access database with http protocol, leave it or change with mysql://ip:3306. Some clients won't accept DNS name for databases so you can check ClusterIP of service and try that IP too.
As mentioned by community member FL3SH you can change your spec.type to clusterIP.
You can reproduce this task using stable helm chart wordpress/mysql.
For newly created pods:
mysql-mariadb-0
mysql-wordpress
and services:
mysql-mariadb
mysql-wordpress
After successfully deployment you can verify if your service is working from the mysql-wordpress pod by running:
kubectl exec -it mysql-wordpress-7cb4958654-tqxm6 -- /bin/bash
In addition, you can install additional tools like nslooukp, telnet:
apt-get update && apt-get install dnsutils telnet
Services and connectivity with db you can test by running f.e. those commands:
nslookup mysql-mariadb
telnet mysql-mariadb 3306
mysql -uroot -hmysql-mariadb -p<your_db_password>
example output:
nslookup mysql-mariadb
Server: 10.125.0.10
Address: 10.125.0.10#53
Non-authoritative answer:
Name: mysql-mariadb.default.svc.cluster.local
Address: 10.125.0.76
mysql -u root -hmysql-mariadb -p<your_db_password>
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 2068
Server version: 10.1.40-MariaDB Source distribution
You should be able to connect using service name or using ip address.
Inside this helm chart you can find also template for statefulset in order to create mysql pods.
Update
From the second pod f.e. ubuntu run this example - Node.js Mysql, install nodes.js and create connection to the database demo_db_connection.js
example:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "mysql-mariadb",
user: "root",
password: "yourpassword"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
run it:
root#ubuntu:~/test# node demo_db_connection.js
Connected!
Try with:
kind: Service
metadata:
labels:
app: mysql
name: mysql
namespace: e-commerce
spec:
clusterIP: None
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
selector:
app: mysql
with the same connection string.
For exmaple, I created network at docker
docker network create hello-rails
Then, I have mySQL, which is connected to this network
docker run -p 3306 -d --network=hello-rails --network-alias=db -e MYSQL_ROOT_PASSWORD=password --name hello-rails-db mysql
And also, I have rails server, which also rely on this network
docker run -it -p 3000:3000 --network=hello-rails -e MYSQL_USER=root -e MYSQL_PASSWORD=password -e MYSQL_HOST=db --name hello-rails benjamincaldwell/hello-docker-rails:latest
I want to write deployment on kubernetes for these two containers with YAML file. But I don't know, how to put network inside containers in the file. Do you have any recommendations?
In Kubernetes you would solve this by creating two services.
The MySQL service will look something like this:
kind: Service
apiVersion: v1
metadata:
name: mysql
spec:
selector:
app: mysql
ports:
- port: 3306
In your rails server, you can access the MySQL service by either using the mysql DNS name or using the MYSQL_SERVICE_HOST and MYSQL_SERVICE_PORT environment variables. There is no need to link the containers or specifying a network, as would be done in Docker.
Your Rails service will look like this:
kind: Service
apiVersion: v1
metadata:
name: rails
spec:
type: LoadBalancer
selector:
app: rails
ports:
- port: 3000
Notice the type: LoadBalancer, which specifies that this service will be published to the outside world. Depending on where you run Kubernetes, a public IP address will be automatically assigned to this service.
For more information, have a look at the Services documentation.
I have the following deployment which puts up MySQL instance:
kind: Deployment
apiVersion: apps/v1beta1
metadata:
name: mysql
spec:
replicas: 1
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-root-password
key: password
The password is just root :
kind: Secret
apiVersion: v1
metadata:
name: mysql-root-password
type: Opaque
data:
password: cm9vdA==
The problem is I try to connect to the instance after port forwarding the MySQL port, following the instructions from here, but get an error:
$ kubectl port-forward mysql-824284009-rpbpk 3306
Forwarding from 127.0.0.1:3306 -> 3306
Forwarding from [::1]:3306 -> 3306
# from another terminal
$ mysql -u root -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
Connecting to the server from the pod itself works:
$ kubectl exec -it mysql-824284009-rpbpk -- /bin/bash
root#mysql-824284009-rpbpk:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
...
mysql>
I have basically the same setup like here, except I'm running the cluster in minikube instead of GCP.
My local MySQL is not runnning, so I assume there is no chance of clashing.
The port forwarding is likely there, but you need to tell mysql client to connect using host/port and not unix socket (default)
mysql --host=localhost --protocol tcp --port=3306 -u root -p
If you don't, mysql by default uses local linux socket to connect to he server: /var/run/mysqld/mysqld.sock .. It even tells you so ;)
Update: As Gabriel checked - adding --protocol tcp had finally made it works, so I am addding it to my answer
How to run mysql: 5.5 from ansible? If I run it directly:
docker run -e MYSQL_ROOT_PASSWORD=pass mysql:5.5
it's work ok. But if I run from ansible:
- name: run database
local_action:
module: docker
image: mysql:5.5
state: running
it's start and immediately stop. Also post in case 1 is 3306/tcp, but in case 2 there is no port.
You need to specify mysql root password as environment variable for container. For example:
- hosts: ansible_host
gather_facts: False
sudo: yes
pre_tasks:
- name: install pip pkg.
yum:
name: python-pip
state: present
- name: install boto pkg.
pip:
name: docker-py
state: present
- name: docker
docker:
image: "mysql:5.5"
state: running
env: "MYSQL_ROOT_PASSWORD=my-secret-pw"