Arjun Karnwal
Arjun Karnwal

Reputation: 379

Run kubectl inside dockerimage

I have application with a DockerFile. This DockerFile needs to run a shell script that have curl commands and kubectl commands.

I have designed the dockerFile as

FROM ubuntu:16.04

WORKDIR /build

RUN apt-get update && apt-get install -y curl && apt-get install -y jq
COPY ./ ./
RUN chmod +x script.sh
ENTRYPOINT ["./script.sh"]

The script.sh file is what contains curl commands and kubectl command.

If you see I have installed curl command inside the docker container using command RUN apt-get update && apt-get install -y curl

What do I need to do in order to run kubectl commands ? Becase when I build and the run the above image, it throws an error saying kubectl: command not found .

Can anyone help me with this ?

Upvotes: 2

Views: 6203

Answers (2)

Mark Watney
Mark Watney

Reputation: 5960

Instead of installing using apt-get, you can download the binary place whatever you want and use it.

This will give you more control under it and less chances to have problems in the future.

Steps on how to download it from the official repository can be fount in the documentation.

Install kubectl binary with curl on Linux

  1. Download the latest release with the command:

    curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl
    

    To download a specific version, replace the $(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt) portion of the command with the specific version.

    For example, to download version v1.18.0 on Linux, type:

    curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
    
  2. Make the kubectl binary executable.

    chmod +x ./kubectl
    
  3. Move the binary in to your PATH.

    sudo mv ./kubectl /usr/local/bin/kubectl
    
  4. Test to ensure the version you installed is up-to-date:

    kubectl version --client
    

Considering this, you can have a Dockerfile similar to this:

FROM debian:buster
RUN apt update && \
      apt install -y curl && \
      curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl && \
      chmod +x ./kubectl && \
      mv ./kubectl /usr/local/bin/kubectl
CMD kubectl get po

After this we can create a pod using the following manifest:

apiVersion: v1
kind: Pod
metadata:
  name: internal-kubectl
spec:
  containers:
    - name: internal-kubectl
      image: myrep/internal-kubectl:latest
      command: ['sh', '-c', "kubectl get pod; sleep 36000"]

Running this pod is going to give you an error and this will happen because you don't have the necessary RBAC rules created.

The way to tell Kubernetes that we want this pod to have an identity that can list the pods is through the combination of a few different resources…

apiVersion: v1
kind: ServiceAccount
metadata:
  name: internal-kubectl

The identity object that we want to assign to our pod will be a service account. But by itself it has no permissions. That’s where roles come in.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: modify-pods
rules:
  - apiGroups: [""]
    resources:
      - pods
    verbs:
      - get
      - list
      - delete

The role above specifies that we want to be able to get, list, and delete pods. But we need a way to correlate our new service account with our new role. Role bindings are the bridges for that…

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: modify-pods-to-sa
subjects:
  - kind: ServiceAccount
    name: internal-kubectl
roleRef:
  kind: Role
  name: modify-pods
  apiGroup: rbac.authorization.k8s.io

This role binding connects our service account to the role that has the permissions we need. Now we just have to modify our pod config to include the service account…

apiVersion: v1
kind: Pod
metadata:
  name: internal-kubectl
spec:
  serviceAccountName: internal-kubectl
  containers:
    - name: internal-kubectl
      image: myrep/internal-kubectl:latest
      command: ['sh', '-c', "kubectl get pod; sleep 36000"]

By specifying spec.serviceAccountName this changes us from using the default service account to our new one that has the correct permissions. Running our new pod we should see the correct output…

$ kubectl logs internal-kubectl
NAME               READY   STATUS    RESTARTS   AGE
internal-kubectl   1/1     Running   1          5s

Upvotes: 4

Sergio Santiago
Sergio Santiago

Reputation: 1514

You can use the kubectl docker image as base and add your personal scripts. Check it here.

Upvotes: 1

Related Questions