I have an error trying to deploy the official phpmyadmin image locally in Kubernetes cluster. Please look at my yaml configs. I haven't any idea what I did wrong. I tried phpmyadmin/phpmyadmin image but the 404 error stays. I also viewed configs from other people but it doesn't differ from mine. This is my first experience in Kubernetes so maybe I don't know some development approaches.
ingress-service.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-service
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- http:
paths:
- path: /phpmyadmin/?(.*)
pathType: Prefix
backend:
service:
name: phpmyadmin-cluster-ip-service
port:
number: 80
phpmyadmin-cluster-ip-service.yaml
apiVersion: v1
kind: Service
metadata:
name: phpmyadmin-cluster-ip-service
spec:
type: ClusterIP
selector:
app: phpmyadmin
ports:
- port: 80
targetPort: 80
protocol: TCP
phpmyadmin-deployment.yaml Ip 192.168.64.7 is given by minikube.
apiVersion: apps/v1
kind: Deployment
metadata:
name: phpmyadmin-deployment
labels:
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: phpmyadmin
tier: backend
template:
metadata:
labels:
app: phpmyadmin
tier: backend
spec:
restartPolicy: Always
containers:
- name: phpmyadmin
image: phpmyadmin:latest
ports:
- name: phpmyadmin
containerPort: 80
protocol: TCP
imagePullPolicy: Always
env:
- name: PMA_ABSOLUTE_URI
value: "http://192.168.64.7/phpmyadmin/"
- name: PMA_VERBOSE
value: "PhpMyAdmin"
- name: PMA_HOST
value: mysql-service
- name: PMA_PORT
value: "3306"
- name: UPLOAD_LIMIT
value: "268435456"
- name: PMA_ARBITRARY
value: "0"
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: MYSQL_ROOT_PASSWORD
I omitted MySQL yaml configs thinking it doesn't related to phpmyadmin issue but if they can help I will pushlish it too.
In this case, adding the annotation nginx.ingress.kubernetes.io/rewrite-target: /$1 will fix it. How? (NOTE: I will change service port to 8080 to better distinguish the ports of the container and Service).
You visit http://<MINIKUBE IP>/phpmyadmin/ on your browser.
The NGINX Ingress controller receives your request, and rewrites the path /phpmyadmin/ to /. The NGINX Ingress controller creates the request to the Service in phpmyadmin-cluster-ip-service at port 8080 (service port) which has the targetPort at 80 (container port) for the pods containing the label app: phpmyadmin. One of the matching pods happens to be at 172.17.0.4:
"GET /phpmyadmin/favicon.ico HTTP/1.1" 200 22486 "-" ... 492 0.001 [default-phpmyadmin-cluster-ip-service-8080] [] 172.17.0.4:80 22486 0.000 200 ...
Because the request is now using the correct path for the phpmyadmin server, it responds with 200 and the requested resource. We can also see the corresponding logs in phpmyadmin:
172.17.0.3 - - [14/Nov/2022:21:58:43 +0000] "GET /favicon.ico HTTP/1.1" 200 22733 "-" ...
The IP 172.17.0.3 is of the NGINX Ingress Controller.
There is also a similar question with an even more detailed answer.
Related
I am trying to solve quite an annoying problem I encounter when using Kubernetes. When I am trying to reach PHPMyAdmin on my server, it returns an Nginx 502 Bad Gateway error.
My structure in my cluster is as follows. I use an Nginx ingress LoadBalancer on DigitalOcean to get traffic into my cluster. It then passes my ingress (in the first code block), which splits the traffic across the subdomains.
When traffic goes to the phpmyadmin subdomain, the request is passed to the 'phpmyadmin-service' with service port 8085.
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: nginx
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: "app1.example.com"
http:
paths:
- path: /
backend:
serviceName: app1-service
servicePort: 80
- host: "phpmyadmin.example.com"
http:
paths:
- path: /
backend:
serviceName: phpmyadmin-service
servicePort: 8085
Then, the service receives the request, and passes it to the 'phpmyadmin-deployment' deployment. This is a deployment that runs the phpmyadmin/phpmyadmin:fpm docker image.
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
name: phpmyadmin-deployment
labels:
app: phpmyadmin
spec:
selector:
matchLabels:
app: phpmyadmin
template:
metadata:
creationTimestamp: null
labels:
app: phpmyadmin
spec:
containers:
- name: phpmyadmin
image: phpmyadmin/phpmyadmin:fpm
ports:
- containerPort: 8087
env:
- name: PMA_ABSOLUTE_URI
value: 'phpmyadmin.example.com'
- name: PMA_HOST
value: mysql
- name: PMA_PORT
value: "3306"
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: rootpw
---
apiVersion: v1
kind: Service
metadata:
name: phpmyadmin-service
spec:
type: ClusterIP
selector:
app: phpmyadmin
ports:
- port: 8085
targetPort: 8087
So something is giving me the 502 Bad Gateway error, and I don't know what it is. Thanks in advance for replying!
I'm new in the k8s world.
Im my dev enviroment, I use ngnix as proxy(with CORS configs and with headers forwarding like ) for the different microservices (all made with spring boot) I have. In a k8s cluster, I had to replace it with Istio?
I'm trying to run a simple microservice(for now) and use Istio for routing to it. I've installed istio with google cloud.
If I navigate to IstioIP/auth/api/v1 it returns 404
This is my yaml file
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
name: http
number: 80
protocol: HTTP
hosts:
- '*'
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: virtual-service
spec:
hosts:
- "*"
gateways:
- gateway
http:
- match:
- uri:
prefix: /auth
route:
- destination:
host: auth-srv
port:
number: 8082
---
apiVersion: v1
kind: Service
metadata:
name: auth-srv
labels:
app: auth-srv
spec:
ports:
- name: http
port: 8082
selector:
app: auth-srv
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: auth-srv
spec:
replicas: 1
template:
metadata:
labels:
app: auth-srv
version: v1
spec:
containers:
- name: auth-srv
image: gcr.io/{{MY_PROJECT_ID}}/auth-srv:1.5
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTS
value: '-DZIPKIN_SERVER=http://zipkin:9411'
ports:
- containerPort: 8082
livenessProbe:
httpGet:
path: /api/v1
port: 8082
initialDelaySeconds: 60
periodSeconds: 5
Looks like istio doesn't know anything about the url. Therefore you are getting a 404 error response.
If you look closer at the configuration in the virtual server you have configured istio to match on path /auth.
So if you try to request ISTIOIP/auth you will reach your microservice application. Here is image to describe the traffic flow and why you are getting a 404 response.
Good Morning. I have a GRPC server that I want to serve on Google Kubernetes Engine. My cluster already has the nginx-ingress controller installed, and I'm currently using this to serve http/https traffic. This is the ingress resource I've tried to make to host the GRPC server:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: grpc-ingress-nginx
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/grpc-backend: "true"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
namespace: default
spec:
tls:
- hosts:
- bar.foo.com
secretName: reploy-tls
rules:
- host: bar.foo.com
http:
paths:
- backend:
serviceName: bar-backend-service
servicePort: 50051
And here's the service/deployment for the app:
apiVersion: v1
kind: Service
metadata:
name: bar-backend-service
namespace: default
spec:
selector:
app: bar-backend-app
ports:
- port: 50051
targetPort: 50051
name: grpc
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: bar-backend
labels:
app: bar-backend-app
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: bar-backend-app
spec:
containers:
- name: bar-backend-image
image: gcr.io/himank-jay/bar-backend-image:TAG
ports:
- containerPort: 50051
name: grpc
When I run grpc_cli ls bar.foo.com:443 (using grpc_cli), I get the following error:
{"created":"#1580833741.460274000","description":"Error received from peer ipv4:x.x.x.x:x","file":"src/core/lib/surface/call.cc","file_line":1055,"grpc_message":"Socket closed","grpc_status":14}
And the error from the nginx-controller is as follows:
x.x.x.x - - [04/Feb/2020:16:28:46 +0000] "PRI * HTTP/2.0" 400 157 "-" "-" 0 0.020 [] [] - - - - xxxxx
Any ideas on what's wrong here? Or any thoughts on how to debug this?
The server is serving HTTP/1.x, not HTTP/2 that's required for gRPC.
You can try adding the following annotation to the Ingress config
nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
...as explained here.
It is also worth checking the use-http2 flag in the nginx configuration (it should be enabled, true, by default).
EDIT, regarding the new error:
PRI * HTTP/2.0 is the so-called HTTP/2 Connection Preface - part of negotiating HTTP/2. It still appears that nginx isn't configured for HTTP/2.
I've set up the following Ingress and deployment for Traefik on Kubernetes. I keep getting a bad gateway error on the actual domain name.
For some reason the service isn't working or I have got the connections wrong or something is amiss with the selectors etc.
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app: wordpress
spec:
selector:
k8s-app: traefik-ingress-lb
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
selector:
app: wordpress
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-ingress
annotations:
kubernetes.io/ingress.class: traefik
# traefik.ingress.kubernetes.io/frontend-entry-points: http,https
spec:
rules:
- host: test.example.services
http:
paths:
- path: /
backend:
serviceName: web
servicePort: http
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: wordpress
labels:
app: wordpress
spec:
selector:
matchLabels:
app: wordpress
tier: frontend
strategy:
type: Recreate
template:
metadata:
labels:
app: wordpress
tier: frontend
spec:
containers:
- image: wordpress:4.8-apache
name: wordpress
env:
- name: WORDPRESS_DB_HOST
value: wordpress-mysql
- name: WORDPRESS_DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-pass
key: password
ports:
- containerPort: 80
name: wordpress
volumeMounts:
- name: wordpress-persistent-storage
mountPath: /var/www/html
volumes:
- name: wordpress-persistent-storage
persistentVolumeClaim:
claimName: wp-pv-claim
My code is below so if there are any corrections to be made, advice is appreciated.
There are few things to consider:
I see that you are missing the namsespace: in your metadata:. Check if that is the case.
Try to create two services. One for wordpress and one for treafik-ingress-lb.
You might have used too many spaces after ports:. Try something like this:
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
Check if your labels are correctly configured. If you need more detials regarding them, try this documentation.
Please let me know if that helped.
I have a gRPC server that works fine on my local machine. I can send grpc requests from a python app and get back the right responses.
I put the server into a GKE cluster (with only one node). I had a normal TCP load balancer in front of the cluster. In this setup my local client was able to get the correct response from some requests, but not others. I think it was the gRPC streaming that didn't work.
I assumed that this is because the streaming requires an HTTP/2 connection which requires SSL.
The standard load balancer I got in GKE didn't seem to support SSL, so I followed the docs to set up an ingress load balancer which does. I'm using a Lets-Encrypt certificate with it.
Now all gRPC requests return
status = StatusCode.UNAVAILABLE
details = "Socket closed"
debug_error_string =
"{"created":"#1556172211.931158414","description":"Error received from
peer
ipv4:ip.of.ingress.service:443", "file":"src/core/lib/surface/call.cc", "file_line":1041,"grpc_message":"Socket closed","grpc_status":14}"
The IP address is the external IP address of my ingress service.
The ingress yaml looks like this:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: rev79-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "rev79-ip"
ingress.gcp.kubernetes.io/pre-shared-cert: "lets-encrypt-rev79"
kubernetes.io/ingress.allow-http: "false" # disable HTTP
spec:
rules:
- host: sub-domain.domain.app
http:
paths:
- path: /*
backend:
serviceName: sandbox-nodes
servicePort: 60000
The subdomain and domain of the request from my python app match the host in the ingress rule.
It connects to a node-port that looks like this:
apiVersion: v1
kind: Service
metadata:
name: sandbox-nodes
spec:
type: NodePort
selector:
app: rev79
environment: sandbox
ports:
- protocol: TCP
port: 60000
targetPort: 9000
The node itself has two containers and looks like this:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rev79-sandbox
labels:
app: rev79
environment: sandbox
spec:
replicas: 1
template:
metadata:
labels:
app: rev79
environment: sandbox
spec:
containers:
- name: esp
image: gcr.io/endpoints-release/endpoints-runtime:1.31
args: [
"--http2_port=9000",
"--service=rev79.endpoints.rev79-232812.cloud.goog",
"--rollout_strategy=managed",
"--backend=grpc://0.0.0.0:3011"
]
ports:
- containerPort: 9000
- name: rev79-uac-sandbox
image: gcr.io/rev79-232812/uac:latest
imagePullPolicy: Always
ports:
- containerPort: 3011
env:
- name: RAILS_MASTER_KEY
valueFrom:
secretKeyRef:
name: rev79-secrets
key: rails-master-key
The target of the node port is the ESP container which connects to the gRPC service deployed in the cloud, and the backend which is a Rails app that implements the backend of the API. This rails app isn't running the rails server, but a specialised gRPC server that comes with the grpc_for_rails gem
The grpc_server in the Rails app doesn't record any action in the logs, so I don't think the request gets that far.
kubectl get ingress reports this:
NAME HOSTS ADDRESS PORTS AGE
rev79-ingress sub-domain.domain.app my.static.ip.addr 80 7h
showing port 80, even though it's set up with SSL. That seems to be a bug. When I check with curl -kv https://sub-domain.domain.app the ingress server handles the request fine, and uses HTTP/2. It reurns an HTML formatted server error, but I'm not sure what generates that.
The API requires an API key, which the python client inserts into the metadata of each request.
When I go to the endpoints page of my GCP console I see that the API is not registering any requests since putting in the ingress loadbalancer, so it looks like the requests are not reaching the EPS container.
So why am I getting "socket closed" errors with gRPC?
I said I would come back and post an answer here once I got it working. It looks like I never did. Being a man of my word I'll post now my config files which are working for me.
in my deployment I've put a liveness and readiness probe for the ESP container. This made deployments happen smoothly without downtime:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rev79-sandbox
labels:
app: rev79
environment: sandbox
spec:
replicas: 3
template:
metadata:
labels:
app: rev79
environment: sandbox
spec:
volumes:
- name: nginx-ssl
secret:
secretName: nginx-ssl
- name: gcs-creds
secret:
secretName: rev79-secrets
items:
- key: gcs-credentials
path: "gcs.json"
containers:
- name: esp
image: gcr.io/endpoints-release/endpoints-runtime:1.45
args: [
"--http_port", "8080",
"--ssl_port", "443",
"--service", "rev79-sandbox.endpoints.rev79-232812.cloud.goog",
"--rollout_strategy", "managed",
"--backend", "grpc://0.0.0.0:3011",
"--cors_preset", "cors_with_regex",
"--cors_allow_origin_regex", ".*",
"-z", " "
]
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 60
timeoutSeconds: 5
periodSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 5
failureThreshold: 1
volumeMounts:
- name: nginx-ssl
mountPath: /etc/nginx/ssl
readOnly: true
ports:
- containerPort: 8080
- containerPort: 443
protocol: TCP
- name: rev79-uac-sandbox
image: gcr.io/rev79-232812/uac:29eff5e
imagePullPolicy: Always
volumeMounts:
- name: gcs-creds
mountPath: "/app/creds"
ports:
- containerPort: 3011
name: end-grpc
- containerPort: 3000
env:
- name: RAILS_MASTER_KEY
valueFrom:
secretKeyRef:
name: rev79-secrets
key: rails-master-key
This is my service config that exposes the deployment to the load balancer:
apiVersion: v1
kind: Service
metadata:
name: rev79-srv-ingress-sandbox
labels:
type: rev79-srv
annotations:
service.alpha.kubernetes.io/app-protocols: '{"rev79":"HTTP2"}'
cloud.google.com/neg: '{"ingress": true}'
spec:
type: NodePort
ports:
- name: rev79
port: 443
protocol: TCP
targetPort: 443
selector:
app: rev79
environment: sandbox
And this is my ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: rev79-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: "rev79-global-ip"
spec:
tls:
- secretName: sandbox-api-rev79-app-tls
rules:
- host: sandbox-api.rev79.app
http:
paths:
- backend:
serviceName: rev79-srv-ingress-sandbox
servicePort: 443
I'm using cert-manager to manage the certificates.
It was a long time agao now. I can't remember if there was anything else I did to solve the issue I was having