operator-framework / operator-sdk

SDK for building Kubernetes applications. Provides high level APIs, useful abstractions, and project scaffolding.
https://sdk.operatorframework.io
Apache License 2.0
7.22k stars 1.74k forks source link

Build go binary without container image #2568

Closed nalbury-handy closed 4 years ago

nalbury-handy commented 4 years ago

Type of question

Are you asking about community best practices, how to implement a specific feature, or about general context and help around the operator-sdk?

Implementation Question

Question

What did you do? Ran operator-sdk build --help

What did you expect to see? A way to build just the go binary

What did you see instead? Under which circumstances? Only ways to build the binary and then build a container image with that binary

Environment

Additional context We have recently removed Docker from our clusters, and are using our own buildkit implementation. This unfortunately means that non of the operator-sdk's build options will work for us. I see this issue, a closed MR to skip image builds via a command line flag, and an issue with lifecycle/frozen about using a Makefile to allow this to be more customizable, all of which leads me believe this isn't a feature that's coming soon.

Is there an easy place to see in the src and/or docs how I can mimic the go build cmd/flags being used by operator-sdk build? Happy to build it ourselves, but would love to avoid using trial and error to get it right.

Thanks! Love the SDK overall, just trying to deploy our first operator :-)

Joibel commented 4 years ago

I was just about to raise an issue for this. We have a similar problem, and would like to build using kaniko, so just want the things built and a Dockerfile to feed that. I have a patch for this, so will do the pull request once I've read the rules.

mhrivnak commented 4 years ago

operator-sdk build is a fairly thin wrapper that basically does go build ... and podman|docker|buildah build .... It's reasonable that some build systems either won't want to or won't be able to make operator-sdk itself available at build time, and that's fine.

It might help to make it more clear in the operator-sdk build help text what it's doing, and perhaps even have a "dry run" option or similar that outputs the exact commands it would have run. That would enable the user to directly run the various build commands, which can also be helpful during troubleshooting and certain development tasks.

camilamacedo86 commented 4 years ago

Hi @nalbury-handy,

Is there an easy place to see in the src and/or docs how I can mimic the go build cmd/flags being used by operator-sdk build? Happy to build it ourselves, but would love to avoid using trial and error to get it right.

The command operator-sdk build will scaffold the files and build the docker image. Also, as you checked it has some options/flags which can be seen by the --help and or doc and its implementation here.

I assume that you are building a Go operator, so you can check the files scaffolded in the Memcached Go as an example.

The structure required/scaffolded in the build dir is:

.
├── Dockerfile
└── bin
    ├── entrypoint
    └── user_setup

See the Dockerfile:

FROM registry.access.redhat.com/ubi8/ubi-minimal:latest

ENV OPERATOR=/usr/local/bin/memcached-operator \
    USER_UID=1001 \
    USER_NAME=memcached-operator

# install operator binary
COPY build/_output/bin/memcached-operator ${OPERATOR}

COPY build/bin /usr/local/bin
RUN  /usr/local/bin/user_setup

ENTRYPOINT ["/usr/local/bin/entrypoint"]

USER ${USER_UID}

Note that it has the ENTRYPOINT ["/usr/local/bin/entrypoint"] is implemented in the bin/ and will be copied for the image. It will exec/start the operator:

#!/bin/sh -e

exec ${OPERATOR} $@

Also, we have the user_setup which will be copied as well:

#!/bin/sh
set -x

# ensure $HOME exists and is accessible by group 0 (we don't know what the runtime UID will be)
mkdir -p ${HOME}
chown ${USER_UID}:0 ${HOME}
chmod ug+rwx ${HOME}

# no need for this script to remain in the image after running
rm $0

It will create the dir and give the required permissions to allow exec the operator with dynamic UIDs which is required for OCP.

So, besides the scaffolded files, it will create the image such as docker build -f build/Dockerfile . which is used to deploy and run the operator in the cluster. In this way, you are able to customize it by a Makefile and do the same in another way. See: https://github.com/operator-framework/operator-sdk/issues/1964

Hi @mhrivnak,

It might help to make it more clear in the operator-sdk build help text what it's doing, and perhaps even have a "dry run" option or similar that outputs the exact commands it would have run. That would enable the user to directly run the various build commands, which can also be helpful during troubleshooting and certain development tasks.

Please, feel free to contribute with a PR with any idea that you may have for improvements over it. However, as described in this issue the goal is to provide a Makefile, see https://github.com/operator-framework/operator-sdk/issues/1655, to allow users to customize it easily which will be achieved by the integration with Kubebuilder. The reason for that is because we are looking for changes in the design to bring more flexibility to our users.

So, in the same way, I think we should not keep open any issue to tracking a requirement as `a "dry run" option or similar that outputs the exact commands for now at least as the same way that others RFE regards this area was closed. Let's see if it will be required after the integration get done. But again, please feel free to raise any idea/suggestion that you might have for it by doing a PR against master.

Hi, @nalbury-handy and @mhrivnak, I am closing this one. However, please let us know if has anything reason for it still open.

nalbury-handy commented 4 years ago

Thanks! this is what I ended up coming up with and it seems to work for our purposes. Read the source code for the build cmd to find the go build ... args. Posting it incase anyone else wants to customize the container image a bit.

FROM golang:1.13-stretch as deps
WORKDIR /src/

COPY ./go.mod /src/go.mod
COPY ./go.sum /src/go.sum

RUN go mod download

# Build stage
FROM deps as build

COPY ./ /src/

RUN env GOOS=linux CGO_ENABLED=0 \
  go build -o ./build/bin/autoscaling-operator \
  -gcflags="all=-trimpath=$(dirname $PWD)" \
  -asmflags="all=-trimpath=$(dirname $PWD)" \
  ./cmd/manager

# Run stage
FROM scratch as run

COPY --from=build /src/build/bin/autoscaling-operator /usr/local/bin/autoscaling-operator

ENTRYPOINT ["/usr/local/bin/autoscaling-operator"]