Search code examples
dockerkubernetesminikubekompose

How to make HTTP/S external calls from Kubernetes pods?


I've used Kompose to translate the following docker-compose to Kubernetes:

---
version: '3'
services:
  freqtrade:
    image: mllamaza/mycoolimg:latest
    restart: unless-stopped
    container_name: mycoolimg
    volumes:
      - "./user_data:/freqtrade/user_data"
    ports:
      - "8080:8080"
    command: >
      start
      --logfile /data/logs/records.log

If I run docker-compose up -d on it, it works perfectly fine. However, when running the equivalent under Kubernetes, the pod is not able to make any external HTTP/S call throwing this error:

urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='mywebsite.com', port=443): Max retries exceeded with url: /my/cool/url/ (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f95197d2a30>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))

Additionally, the image has a frontend webpage too that can be accessed from http://0.0.0.0:8080.

I use Minikube, and their documentation stays that:

Services of type LoadBalancer can be exposed via the minikube tunnel command. It must be run in a separate terminal window to keep the LoadBalancer running.

That's exactly what I did, that command shows no errors:

❯ minikube tunnel           
[sudo] password for mllamaza: 
Status:
        machine: minikube
        pid: 1513359
        route: 10.96.0.0/12 -> 192.168.49.2
        minikube: Running
        services: []
    errors: 
                minikube: no errors
                router: no errors
                load balancer emulator: no errors

But, as you can see, the pod has failed because it cannot access external IP's (I checked the logs), and the service/mycoolimg does not have an external IP configured as shown in the documentation:

❯ k get all
NAME                             READY   STATUS             RESTARTS      AGE
pod/mycoolimg-868cdd75bf-krgp6   0/1     CrashLoopBackOff   2 (15s ago)   47s

NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
service/mycoolimg    ClusterIP   10.105.7.210   <none>        8080/TCP   47s
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP    2d13h

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/mycoolimg   0/1     1            0           47s

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/mycoolimg-868cdd75bf   1         1         0       47s

What am I missing? Is this a Kompose conversion issue, and Minikube specific configuration or am I missing some Kubernetes step?

This is the service output:

apiVersion: v1
kind: Service
metadata:
  annotations:
    kompose.cmd: kompose convert --volumes hostPath -o ./deployment
    kompose.version: 1.26.0 (40646f47)
  creationTimestamp: null
  labels:
    io.kompose.service: mycoolimg
  name: mycoolimg
spec:
  ports:
    - name: "8080"
      port: 8080
      targetPort: 8080
  selector:
    io.kompose.service: mycoolimg
status:
  loadBalancer: {}

And this the deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    kompose.cmd: kompose convert --volumes hostPath -o ./deployment
    kompose.version: 1.26.0 (40646f47)
  creationTimestamp: null
  labels:
    io.kompose.service: mycoolimg
  name: mycoolimg
spec:
  replicas: 1
  selector:
    matchLabels:
      io.kompose.service: mycoolimg
  strategy:
    type: Recreate
  template:
    metadata:
      annotations:
        kompose.cmd: kompose convert --volumes hostPath -o ./deployment
        kompose.version: 1.26.0 (40646f47)
      creationTimestamp: null
      labels:
        io.kompose.service: mycoolimg
    spec:
      containers:
        - args:
            - start
            - --logfile 
            - /data/logs/records.log
          image: mllamaza/mycoolimg:latest
          name: mycoolimg
          ports:
            - containerPort: 8080
          resources: {}
          volumeMounts:
            - mountPath: /data
              name: mycoolimg-hostpath0
      restartPolicy: Always
      volumes:
        - hostPath:
            path: /udata
          name: mycoolimg-hostpath0
status: {}

Solution

  • The first thing you should be looking at is the CrashLoopBackOff error on your pod, this is an indication that something is going on in that container which is crashing your pod, you can find a very good article here on how to debug this error 1.

    Based on the information and code provided the problem seems to be with the application itself; more precisely with the way Docker and Kubernetes handle entrypoints and commands, perhaps an entrypoint was passed as command to Kubernetes or vice versa?

    Came to that conclusion after running a pod successfully by replicating your environment but with a different image and taking out the start command:

    ---
    version: '3'
    services:
      freqtrade:
        image: expressjs
        restart: unless-stopped
        container_name: mycoolimg
        volumes:
          - "./user_data:/freqtrade/user_data"
        ports:
          - "8080:8080"
    #    command: >
    #      start
    #      --logfile /data/logs/records.log
    

    using kompose to convert to kubernetes with command kompose convert --volumes hostPath I get the following output:

    WARN Restart policy 'unless-stopped' in service freqtrade is not supported, convert it to 'always' 
    INFO Kubernetes file "freqtrade-service.yaml" created 
    INFO Kubernetes file "freqtrade-deployment.yaml" created 
    

    Applying the deployment with command kubectl apply -f freqtrade-deployment.yaml and I can see the pod running:

    NAME                         READY   STATUS    RESTARTS      AGE
    freqtrade-86cd7d4469-dkhmw   1/1     Running   0             7s
    

    Note: Depending on the method you are using to push/pull your images in minikube 2, you may need to add imagePullPolicy: Never under your containers spec:

        spec:
          containers:
            - image: expressjs
              imagePullPolicy: Never
              name: mycoolimg
              ports:
                - containerPort: 8080