Upgrade Advisory
This documentation is for Flux (v1) and Helm Operator (v1). Both projects are in maintenance mode and will soon reach end-of-life. We strongly recommend you familiarise yourself with the newest Flux and start looking at your migration path.
For documentation regarding the latest Flux, please refer to this section.
Get started developing
This guide shows a workflow for making a small (actually, tiny) change to Flux, building and testing that change locally.
TL;DR
From a very high level, there are at least 3 ways you can develop on Flux once you have your environment set up:
-
The “minimalist” approach (only requires and
kubectl):make- copy the specific image tag (e.g.
docker.io/fluxcd/flux:master-a86167e4) for what you just built and paste it into/deploy/flux-deployment.yamlas the image you’re targeting to deploy - deploy the resources in
/develop/*.yamlmanually withkubectl apply - make a change to the code
- see your code changes have been deployed
- repeat
-
Use
freshpodto deploy changes to the/deploydirectory resources:make- make a change to the code
- see your changes have been deployed
- repeat
-
Remote cluster development approach:
- ensure local
kubectlaccess to a remote Kubernetes cluster - have an available local memcached instance
- make a change to the code
-
go run cmd/fluxd/main.go \ --memcached-hostname localhost \ --memcached-port 11211 \ --memcached-service "" \ --git-url git@github.com:fluxcd/flux-get-started \ --k8s-in-cluster=false
- ensure local
This guide covers approaches 1 and 2 using minikube. freshpod is
superseded by Skaffold and is generally the future. That said,
freshpod is very simple to use and reason about (and is still well
supported by minikube) which is why it’s used in this guide.
Run fluxcd/flux-getting-started
We’re going to make some changes soon enough, but just to get a good
baseline please follow the
“Get started with Flux”
tutorial and run the fluxcd/flux-getting-started repo through its
normal paces.
Now that we know everything is working with flux-getting-started,
we’re going to try and do nearly the same thing as flux-getting-started,
except instead of using official releases of flux, we’re going to build
and run what we have locally.
Prepare your environment
-
Install the prerequisites. This guide is written from running Linux, but the same instructions will generally apply to OSX. Although everything you need has been known to work independently in Windows from time to time, results may vary.
-
Configure your environment so you can run tests. Run:
make test -
We want to make sure we’re starting fresh. Tell
minikubeto clear any previously running clusters:minikube delete -
The
minikubeaddon called freshpod that will be very useful to us later. You’ll see. It’s gonna be cool.minikube addons enable freshpod -
This part is really important. You’re going to set some environment variables which will intercept any images pulled by docker. Run
minikube docker-envto see what we’re talking about. You’ll get an output that shows you what the script is doing. Thankfully, it’s not terribly complicated - it just sets some environment variables which will allowminikubeto man-in-the-middle the requests Kubernetes makes to pull images. It will look something like this:export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.128:2376" export DOCKER_CERT_PATH="/home/fluxrulez/.minikube/certs" export DOCKER_API_VERSION="1.35" # Run this command to configure your shell: # eval $(minikube docker-env)So, as the script suggests, run the following command:
eval $(minikube docker-env)Now, be warned. These are local variables. This means that if you run this
evalin one terminal and then switch to another for later when we build the Flux project, you’re gonna hit some issues. For one, you’ll know it isn’t working because Kubernetes will tell you that it can’t pull the image when you runkubectl get pods:NAME READY STATUS RESTARTS AGE flux-7f6bd57699-shx9v 0/1 ErrImagePull 0 35s
Prepare the repository
-
Fork the repo on GitHub.
-
Clone
git@github.com:<YOUR-GITHUB-USERNAME>/flux.gitreplacing<YOUR-GITHUB-USERNAME>with your GitHub username.In the same terminal you ran
eval $(minikube docker-env), runGO111MODULE=on go mod downloadfollowed bymakefrom the root directory of the Flux repo. You’ll see docker’s usual output as it builds the image layers. Once it’s done, you should see something like this in the middle of the output:Successfully built 606610e0f4ef Successfully tagged docker.io/fluxcd/flux:latest Successfully tagged docker.io/fluxcd/flux:master-a86167e4This confirms that a new docker image was tagged for your image.
-
Open up
deploy/flux-deployment.yamland update the image atspec.template.spec.containers[0].imageto be simplydocker.io/fluxcd/flux. While we’re here, also change the--git-urlto point towards your fork. It will look something like this in the YAML:spec: template: spec: containers: - name: flux image: docker.io/fluxcd/flux imagePullPolicy: IfNotPresent args: - --git-url=git@github.com:<YOUR-GITHUB-USERNAME>/flux-getting-started - --git-branch=master -
We’re ready to apply your newly-customized deployment! Since
kubectlwill apply all the Kubernetes manifests it finds (recursively) in a folder, we simply need to pass the directory tokubectl apply:kubectl apply --filename ./deployYou should see an output similar to:
serviceaccount/flux created clusterrole.rbac.authorization.k8s.io/flux created clusterrolebinding.rbac.authorization.k8s.io/flux created deployment.apps/flux created secret/flux-git-deploy created deployment.apps/memcached created service/memcached created secret/flux-git-deploy configuredCongrats you just deployed your local Flux to your default namespace. Check that everything is running:
kubectl get pods --selector=name=fluxYou should get an output that looks like:
NAME READY STATUS RESTARTS AGE flux-6f7fd5bbc-hpq85 1/1 Running 0 38sIf (instead) you see that Ready is showing
0/1and/or the status isErrImagePulldouble back on the instructions and make sure you did everything correctly and in order. -
Pull the logs for your “fresh off of master” copy of Flux that you just deployed locally to
minikube:kubectl logs --selector=name=fluxYou should see an output that looks something like this:
ts=2019-02-28T18:58:45.091531939Z caller=warming.go:268 component=warmer info="refreshing image" image=docker.io/fluxcd/flux tag_count=60 to_update=60 of_which_refresh=0 of_which_missing=60 ts=2019-02-28T18:58:46.233723421Z caller=warming.go:364 component=warmer updated=docker.io/fluxcd/flux successful=60 attempted=60 ts=2019-02-28T18:58:46.234086642Z caller=images.go:17 component=sync-loop msg="polling images" ts=2019-02-28T18:58:46.234125646Z caller=images.go:27 component=sync-loop msg="no automated services" ts=2019-02-28T18:58:46.749598558Z caller=warming.go:268 component=warmer info="refreshing image" image=memcached tag_count=66 to_update=66 of_which_refresh=0 of_which_missing=66 ts=2019-02-28T18:58:51.017452675Z caller=warming.go:364 component=warmer updated=memcached successful=66 attempted=66 ts=2019-02-28T18:58:51.020061586Z caller=images.go:17 component=sync-loop msg="polling images" ts=2019-02-28T18:58:51.020113243Z caller=images.go:27 component=sync-loop msg="no automated services"
Make some changes
-
Now for the part you’ve been waiting for! We’re going to make a cosmetic change to our local copy of Flux. Navigate to git/operations.go. In it, you will find a private function to this package that goes by the name
execGitCmd. Paste the following as the (new) first line of the function:fmt.Println("executing git command ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ") -
Run
makeagain. Once this finishes you can check on your running pods with:kubectl get pods --selector=name=fluxKeep your eye on the
AGEcolumn. It should be just a few seconds old if you check out theAGEcolumn:NAME READY STATUS RESTARTS AGE flux-6f7fd5bbc-6j9d5 1/1 Running 0 10sThis pod was deployed even though we didn’t run any
kubectlcommands or interact with Kubernetes directly because of thefreshpodminikubeaddon that we enabled earlier. Freshpod saw that a new Docker image was tagged fordocker.io/fluxcd/flux:latestand it went ahead and redeployed that pod for us.Consider that simply applying the
flux-deployment.yamlfile again wouldn’t do anything since the actual image we’re targeting (which is actuallydocker.io/fluxcd/fluxwith no:latesttag, but it’s the same difference) hasn’t changed. The Kubernetes api server will get that JSON request fromkubectland go: “right… so nothing has changed in the file so I have nothing to do… IGNORE!”.There is another way to do this, of course. Remember that before when we ran
makethat we did also get an image tagged with the:<branch>-<commit hash>syntax (in our specific example above it was:master-a86167e4). We could, in theory, grab that tag every time wemake, and then paste it intospec.template.spec.containers[0].imageof our deployment. That’s tedious and error prone. Instead,freshpodcuts this step out for us and accomplishes the same end goal. -
Check the logs again (with
kubectl logs --selector=name=flux) to find that your obnoxious chain ofZs is present.
Congratulations!
You have now modified Flux and deployed that change locally. From here
on out, you simply need to run make after you save your changes and
wait a few seconds for your new pod to be deployed to minikube.
Keep in mind, that (as in the situation where you run make without
saving any changes) if the Docker image you pointed to in the
Kubernetes deployment for Flux is not Successfully tagged, freshpod
won’t have anything new to deploy.
Other than that, you should be good to go!