diff --git a/.github/workflows/push_image.yml b/.github/workflows/push_image.yml index 735fd1b1f..492d00034 100644 --- a/.github/workflows/push_image.yml +++ b/.github/workflows/push_image.yml @@ -5,10 +5,9 @@ on: env: REGISTRY_USER: netobserv+github_ci - REGISTRY_PASSWORD: ${{ secrets.QUAY_SECRET }} REGISTRY: quay.io/netobserv IMAGE: flowlogs-pipeline - TAG: main + VERSION: main jobs: push-image: @@ -30,7 +29,7 @@ jobs: uses: docker/login-action@v2 with: username: ${{ env.REGISTRY_USER }} - password: ${{ env.REGISTRY_PASSWORD }} + password: ${{ secrets.QUAY_SECRET }} registry: quay.io - - name: build and push images - run: OCI_RUNTIME=docker DOCKER_TAG=${{ env.TAG }} make push-ci-images + - name: build and push manifest with images + run: OCI_BIN=docker VERSION=${{ env.VERSION }} make ci diff --git a/.github/workflows/push_image_pr.yml b/.github/workflows/push_image_pr.yml index 7c1f047a8..9a8c3b9c6 100644 --- a/.github/workflows/push_image_pr.yml +++ b/.github/workflows/push_image_pr.yml @@ -7,6 +7,7 @@ env: REGISTRY_USER: netobserv+github_ci REGISTRY: quay.io/netobserv IMAGE: flowlogs-pipeline + VERSION: temp jobs: push-pr-image: @@ -35,9 +36,10 @@ jobs: registry: quay.io - name: get short sha run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_ENV - - name: build and push images - run: OCI_RUNTIME=docker DOCKER_TAG=temp make push-ci-images + run: OCI_BIN=docker IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE }}:$(( env.short_sha )) make images + - name: build and push manifest + run: OCI_BIN=docker VERSION=${{ env.VERSION }} make ci-manifest - uses: actions/github-script@v6 with: github-token: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a53842870..4d7f3bb2f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,4 +43,4 @@ jobs: password: ${{ env.REGISTRY_PASSWORD }} registry: quay.io - name: build and push images - run: OCI_RUNTIME=docker DOCKER_TAG=${{ env.tag }} make push-multiarch-manifest + run: OCI_BIN=docker VERSION=${{ env.tag }} make images diff --git a/.mk/development.mk b/.mk/development.mk new file mode 100644 index 000000000..47d7d07ad --- /dev/null +++ b/.mk/development.mk @@ -0,0 +1,156 @@ +##@ kubernetes + +# note: to deploy with custom image tag use: VERSION=test make deploy +.PHONY: deploy +deploy: ## Deploy the image + sed 's|%IMAGE_TAG_BASE%|$(IMAGE_TAG_BASE)|g;s|%VERSION%|$(VERSION)|g' contrib/kubernetes/deployment.yaml > /tmp/deployment.yaml + kubectl create configmap flowlogs-pipeline-configuration --from-file=flowlogs-pipeline.conf.yaml=$(FLP_CONF_FILE) + kubectl apply -f /tmp/deployment.yaml + kubectl rollout status "deploy/flowlogs-pipeline" --timeout=600s + +.PHONY: undeploy +undeploy: ## Undeploy the image + sed 's|%IMAGE_TAG_BASE%|$(IMAGE_TAG_BASE)|g;s|%VERSION%|$(VERSION)|g' contrib/kubernetes/deployment.yaml > /tmp/deployment.yaml + kubectl --ignore-not-found=true delete configmap flowlogs-pipeline-configuration || true + kubectl --ignore-not-found=true delete -f /tmp/deployment.yaml || true + +.PHONY: deploy-loki +deploy-loki: ## Deploy loki + kubectl apply -f contrib/kubernetes/deployment-loki-storage.yaml + kubectl apply -f contrib/kubernetes/deployment-loki.yaml + kubectl rollout status "deploy/loki" --timeout=600s + -pkill --oldest --full "3100:3100" + kubectl port-forward --address 0.0.0.0 svc/loki 3100:3100 2>&1 >/dev/null & + @echo -e "\nloki endpoint is available on http://localhost:3100\n" + +.PHONY: undeploy-loki +undeploy-loki: ## Undeploy loki + kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-loki.yaml || true + kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-loki-storage.yaml || true + -pkill --oldest --full "3100:3100" + +.PHONY: deploy-prometheus +deploy-prometheus: ## Deploy prometheus + kubectl apply -f contrib/kubernetes/deployment-prometheus.yaml + kubectl rollout status "deploy/prometheus" --timeout=600s + -pkill --oldest --full "9090:9090" + kubectl port-forward --address 0.0.0.0 svc/prometheus 9090:9090 2>&1 >/dev/null & + @echo -e "\nprometheus ui is available on http://localhost:9090\n" + +.PHONY: undeploy-prometheus +undeploy-prometheus: ## Undeploy prometheus + kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-prometheus.yaml || true + -pkill --oldest --full "9090:9090" + +.PHONY: deploy-grafana +deploy-grafana: ## Deploy grafana + kubectl create configmap grafana-dashboard-definitions --from-file=contrib/dashboards/ + kubectl apply -f contrib/kubernetes/deployment-grafana.yaml + kubectl rollout status "deploy/grafana" --timeout=600s + -pkill --oldest --full "3000:3000" + kubectl port-forward --address 0.0.0.0 svc/grafana 3000:3000 2>&1 >/dev/null & + @echo -e "\ngrafana ui is available (user: admin password: admin) on http://localhost:3000\n" + +.PHONY: undeploy-grafana +undeploy-grafana: ## Undeploy grafana + kubectl --ignore-not-found=true delete configmap grafana-dashboard-definitions || true + kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-grafana.yaml || true + -pkill --oldest --full "3000:3000" + +.PHONY: deploy-netflow-simulator +deploy-netflow-simulator: ## Deploy netflow simulator + kubectl apply -f contrib/kubernetes/deployment-netflow-simulator.yaml + kubectl rollout status "deploy/netflowsimulator" --timeout=600s + +.PHONY: undeploy-netflow-simulator +undeploy-netflow-simulator: ## Undeploy netflow simulator + kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-netflow-simulator.yaml || true + +##@ kind + +.PHONY: create-kind-cluster +create-kind-cluster: $(KIND) ## Create cluster + $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --config contrib/kubernetes/kind/kind.config.yaml + kubectl cluster-info --context kind-kind + +.PHONY: delete-kind-cluster +delete-kind-cluster: $(KIND) ## Delete cluster + $(KIND) delete cluster --name $(KIND_CLUSTER_NAME) + +.PHONY: kind-load-image +kind-load-image: ## Load image to kind +ifeq ($(OCI_BIN),$(shell which docker)) +# This is an optimization for docker provider. "kind load docker-image" can load an image directly from docker's +# local registry. For other providers (i.e. podman), we must use "kind load image-archive" instead. + $(KIND) load --name $(KIND_CLUSTER_NAME) docker-image $(IMAGE)-${GOARCH} +else + $(eval tmpfile="/tmp/flp.tar") + -rm $(tmpfile) + $(OCI_BIN) save $(IMAGE)-$(GOARCH) -o $(tmpfile) + $(KIND) load --name $(KIND_CLUSTER_NAME) image-archive $(tmpfile) + -rm $(tmpfile) +endif + +##@ metrics + +.PHONY: generate-configuration +generate-configuration: $(KIND) ## Generate metrics configuration + go build "${CMD_DIR}${CG_BIN_FILE}" + ./${CG_BIN_FILE} --log-level debug --srcFolder network_definitions \ + --destConfFile $(FLP_CONF_FILE) \ + --destDocFile docs/metrics.md \ + --destGrafanaJsonnetFolder contrib/dashboards/jsonnet/ + +##@ End2End + +.PHONY: local-deployments-deploy +local-deployments-deploy: $(KIND) deploy-prometheus deploy-loki deploy-grafana build-image kind-load-image deploy deploy-netflow-simulator + kubectl get pods + kubectl rollout status -w deployment/flowlogs-pipeline + kubectl logs -l app=flowlogs-pipeline + +.PHONY: local-deploy +local-deploy: $(KIND) local-cleanup create-kind-cluster local-deployments-deploy ## Deploy locally on kind (with simulated flowlogs) + +.PHONY: local-deployments-cleanup +local-deployments-cleanup: $(KIND) undeploy-netflow-simulator undeploy undeploy-grafana undeploy-loki undeploy-prometheus + +.PHONY: local-cleanup +local-cleanup: $(KIND) local-deployments-cleanup delete-kind-cluster ## Undeploy from local kind + +.PHONY: local-redeploy +local-redeploy: local-deployments-cleanup local-deployments-deploy ## Redeploy locally (on current kind) + +.PHONY: ocp-deploy +ocp-deploy: ocp-cleanup deploy-prometheus deploy-loki deploy-grafana deploy ## Deploy to OCP + flowlogs_pipeline_svc_ip=$$(kubectl get svc flowlogs-pipeline -o jsonpath='{.spec.clusterIP}'); \ + ./hack/enable-ocp-flow-export.sh $$flowlogs_pipeline_svc_ip + kubectl get pods + kubectl rollout status -w deployment/flowlogs-pipeline + kubectl logs -l app=flowlogs-pipeline + oc expose service prometheus || true + @prometheus_url=$$(oc get route prometheus -o jsonpath='{.spec.host}'); \ + echo -e "\nAccess prometheus on OCP using: http://"$$prometheus_url"\n" + oc expose service grafana || true + @grafana_url=$$(oc get route grafana -o jsonpath='{.spec.host}'); \ + echo -e "\nAccess grafana on OCP using: http://"$$grafana_url"\n" + oc expose service loki || true + @loki_url=$$(oc get route loki -o jsonpath='{.spec.host}'); \ + echo -e "\nAccess loki on OCP using: http://"$$loki_url"\n" + +.PHONY: ocp-cleanup +ocp-cleanup: undeploy undeploy-loki undeploy-prometheus undeploy-grafana ## Undeploy from OCP + +.PHONY: dev-local-deploy +dev-local-deploy: ## Deploy locally with simulated netflows + -pkill --oldest --full "${FLP_BIN_FILE}" + -pkill --oldest --full "${NETFLOW_GENERATOR}" + go build "${CMD_DIR}${FLP_BIN_FILE}" + go build "${CMD_DIR}${CG_BIN_FILE}" + ./${CG_BIN_FILE} --log-level debug --srcFolder network_definitions \ + --skipWithTags "kubernetes" \ + --destConfFile /tmp/flowlogs-pipeline.conf.yaml --destGrafanaJsonnetFolder /tmp/ + test -f /tmp/${NETFLOW_GENERATOR} || curl -L --output /tmp/${NETFLOW_GENERATOR} https://github.com/nerdalert/nflow-generator/blob/master/binaries/nflow-generator-x86_64-linux?raw=true + chmod +x /tmp/${NETFLOW_GENERATOR} + ./"${FLP_BIN_FILE}" --config /tmp/flowlogs-pipeline.conf.yaml & + /tmp/${NETFLOW_GENERATOR} -t 127.0.0.1 -p 2056 > /dev/null 2>&1 & \ No newline at end of file diff --git a/.mk/shortcuts.mk b/.mk/shortcuts.mk new file mode 100644 index 000000000..bbd30355d --- /dev/null +++ b/.mk/shortcuts.mk @@ -0,0 +1,28 @@ +##@ shortcuts helpers + +.PHONY: build-image +build-image: image-build ## Build MULTIARCH_TARGETS images + +.PHONY: push-image +push-image: image-push ## Push MULTIARCH_TARGETS images + +.PHONY: build-manifest +build-manifest: manifest-build ## Build MULTIARCH_TARGETS manifest + +.PHONY: push-manifest +push-manifest: manifest-push ## Push MULTIARCH_TARGETS manifest + +.PHONY: images +images: image-build image-push manifest-build manifest-push ## Build and push MULTIARCH_TARGETS images and related manifest + +.PHONY: build-ci-manifest +build-ci-manifest: ci-manifest-build ## Build CI manifest + +.PHONY: push-ci-manifest +push-ci-manifest: ci-manifest-push ## Push CI manifest + +.PHONY: ci-manifest +ci-manifest: ci-manifest-build ci-manifest-push ## Build and push CI manifest + +.PHONY: ci +ci: images ci-manifest ## Build and push CI images and manifest \ No newline at end of file diff --git a/Makefile b/Makefile index bd49a5dc7..ebfc51891 100644 --- a/Makefile +++ b/Makefile @@ -9,37 +9,66 @@ export GO111MODULE=on export CGO_ENABLED=0 export GOOS=linux -GOARCH ?= amd64 - -SHELL := /usr/bin/env bash -DOCKER_TAG ?= latest -DOCKER_IMG ?= quay.io/netobserv/flowlogs-pipeline -OCI_RUNTIME_PATH = $(shell which podman || which docker) -OCI_RUNTIME ?= $(shell echo '$(OCI_RUNTIME_PATH)'|sed -e 's/.*\/\(.*\)/\1/g') -MIN_GO_VERSION := 1.18.0 -FLP_BIN_FILE=flowlogs-pipeline -CG_BIN_FILE=confgenerator -NETFLOW_GENERATOR=nflow-generator -CMD_DIR=./cmd/ -FLP_CONF_FILE ?= contrib/kubernetes/flowlogs-pipeline.conf.yaml -KIND_CLUSTER_NAME ?= kind - +# VERSION defines the project version for the bundle. +# Update this value when you upgrade the version of your project. +# To re-generate a bundle for another specific version without changing the standard setup, you can: +# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) +# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) +VERSION ?= latest BUILD_DATE := $(shell date +%Y-%m-%d\ %H:%M) TAG_COMMIT := $(shell git rev-list --abbrev-commit --tags --max-count=1) TAG := $(shell git describe --abbrev=0 --tags ${TAG_COMMIT} 2>/dev/null || true) -COMMIT := $(shell git rev-parse --short HEAD) +BUILD_SHA := $(shell git rev-parse --short HEAD) BUILD_VERSION := $(TAG:v%=%) ifneq ($(COMMIT), $(TAG_COMMIT)) - BUILD_VERSION := $(BUILD_VERSION)-$(COMMIT) + BUILD_VERSION := $(BUILD_VERSION)-$(BUILD_SHA) endif ifneq ($(shell git status --porcelain),) BUILD_VERSION := $(BUILD_VERSION)-dirty endif +# Go architecture and targets images to build +GOARCH ?= amd64 +MULTIARCH_TARGETS := amd64 arm64 ppc64le + +# In CI, to be replaced by `netobserv` +IMAGE_ORG ?= $(USER) + +# IMAGE_TAG_BASE defines the namespace and part of the image name for remote images. +IMAGE_TAG_BASE ?= quay.io/$(IMAGE_ORG)/flowlogs-pipeline + +# Image URL to use all building/pushing image targets +IMAGE = $(IMAGE_TAG_BASE):$(VERSION) +IMAGE_SHA = $(IMAGE_TAG_BASE):$(BUILD_SHA) + +# Image building tool (docker / podman) +OCI_BIN_PATH = $(shell which podman || which docker) +OCI_BIN ?= $(shell v='$(OCI_BIN_PATH)'; echo "$${v##*/}") + +MIN_GO_VERSION := 1.18.0 +FLP_BIN_FILE=flowlogs-pipeline +CG_BIN_FILE=confgenerator +NETFLOW_GENERATOR=nflow-generator +CMD_DIR=./cmd/ +FLP_CONF_FILE ?= contrib/kubernetes/flowlogs-pipeline.conf.yaml +KIND_CLUSTER_NAME ?= kind + .DEFAULT_GOAL := help FORCE: ; +# build a single arch target provided as argument +define build_target + echo 'building image for arch $(1)'; \ + DOCKER_BUILDKIT=1 $(OCI_BIN) buildx build --load --build-arg TARGETPLATFORM=linux/$(1) --build-arg TARGETARCH=$(1) --build-arg BUILDPLATFORM=linux/amd64 -t ${IMAGE}-$(1) -f contrib/docker/Dockerfile .; +endef + +# push a single arch target image +define push_target + echo 'pushing image ${IMAGE}-$(1)'; \ + DOCKER_BUILDKIT=1 $(OCI_BIN) push ${IMAGE}-$(1); +endef + ##@ General # The help target prints out all targets with their descriptions organized @@ -57,6 +86,11 @@ FORCE: ; help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +.PHONY: vendors +vendors: ## Check go vendors + @echo "### Checking vendors" + go mod tidy && go mod vendor + .PHONY: validate_go validate_go: @current_ver=$$(go version | { read _ _ v _; echo $${v#go}; }); \ @@ -119,215 +153,49 @@ benchmarks: $(BENCHSTAT) validate_go ## Benchmark run: build ## Run ./"${FLP_BIN_FILE}" -##@ Docker - -# note: to build and push custom image tag use: DOCKER_TAG=test make push-image -.PHONY: build-image -build-image: - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) build -t $(DOCKER_IMG):$(DOCKER_TAG) -f contrib/docker/Dockerfile . - -# It would have been better to have -build-single-multiarch-linux/%: -#The --load option is ignored by podman but required for docker - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) buildx build --load --build-arg TARGETPLATFORM=linux/$* --build-arg TARGETARCH=$* --build-arg BUILDPLATFORM=linux/amd64 -t $(DOCKER_IMG):$(DOCKER_TAG)-$* -f contrib/docker/Dockerfile . - -# It would have been better to have -push-single-multiarch-linux/%: build-single-multiarch-linux/% -#The --load option is ignored by podman but required for docker - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) push $(DOCKER_IMG):$(DOCKER_TAG)-$* - -# note: to build and push custom image tag use: DOCKER_TAG=test make push-image -.PHONY: build-multiarch-manifest -build-multiarch-manifest: push-single-multiarch-linux/amd64 push-single-multiarch-linux/arm64 push-single-multiarch-linux/ppc64le - #if using Docker, image needs to be pushed before beeing added to the manifest - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) manifest create $(DOCKER_IMG):$(DOCKER_TAG) --amend $(DOCKER_IMG):$(DOCKER_TAG)-amd64 --amend $(DOCKER_IMG):$(DOCKER_TAG)-arm64 --amend $(DOCKER_IMG):$(DOCKER_TAG)-ppc64le - -.PHONY: push-multiarch-manifest -push-multiarch-manifest: build-multiarch-manifest - @echo 'publish manifest $(DOCKER_TAG) to $(DOCKER_IMG)' -ifeq (${OCI_RUNTIME} , docker) - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) manifest push $(DOCKER_IMG):$(DOCKER_TAG) +##@ Images + +# note: to build and push custom image tag use: IMAGE_ORG=myuser VERSION=dev make images +.PHONY: image-build +image-build: ## Build MULTIARCH_TARGETS images + trap 'exit' INT; \ + $(foreach target,$(MULTIARCH_TARGETS),$(call build_target,$(target))) + +.PHONY: image-push +image-push: ## Push MULTIARCH_TARGETS images + trap 'exit' INT; \ + $(foreach target,$(MULTIARCH_TARGETS),$(call push_target,$(target))) + +.PHONY: manifest-build +manifest-build: ## Build MULTIARCH_TARGETS manifest + @echo 'building manifest $(IMAGE)' + DOCKER_BUILDKIT=1 $(OCI_BIN) manifest create ${IMAGE} $(foreach target,$(MULTIARCH_TARGETS),--amend ${IMAGE}-$(target)); + +.PHONY: manifest-push +manifest-push: ## Push MULTIARCH_TARGETS manifest + @echo 'publish manifest $(IMAGE)' +ifeq (${OCI_BIN}, docker) + DOCKER_BUILDKIT=1 $(OCI_BIN) manifest push ${IMAGE}; else - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) manifest push $(DOCKER_IMG):$(DOCKER_TAG) docker://$(DOCKER_IMG):$(DOCKER_TAG) + DOCKER_BUILDKIT=1 $(OCI_BIN) manifest push ${IMAGE} docker://${IMAGE}; endif - -.PHONY: build-ci-images -build-ci-images: -ifeq ($(DOCKER_TAG), main) +.PHONY: ci-manifest-build +ci-manifest-build: manifest-build ## Build CI manifest + $(OCI_BIN) build --build-arg BASE_IMAGE=$(IMAGE) -t $(IMAGE_SHA) -f contrib/docker/shortlived.Dockerfile . +ifeq ($(VERSION), main) # Also tag "latest" only for branch "main" - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) build -t $(DOCKER_IMG):$(DOCKER_TAG) -t $(DOCKER_IMG):latest -f contrib/docker/Dockerfile . -else - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) build -t $(DOCKER_IMG):$(DOCKER_TAG) -f contrib/docker/Dockerfile . -endif - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) build --build-arg BASE_IMAGE=$(DOCKER_IMG):$(DOCKER_TAG) -t $(DOCKER_IMG):$(COMMIT) -f contrib/docker/shortlived.Dockerfile . - -.PHONY: push-ci-images -push-ci-images: build-ci-images - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) push $(DOCKER_IMG):$(COMMIT) -ifeq ($(DOCKER_TAG), main) - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) push $(DOCKER_IMG):$(DOCKER_TAG) - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) push $(DOCKER_IMG):latest + $(OCI_BIN) build -t $(IMAGE) -t $(IMAGE_TAG_BASE):latest -f contrib/docker/Dockerfile . endif -.PHONY: push-image -push-image: build-image ## Push latest image - @echo 'publish image $(DOCKER_TAG) to $(DOCKER_IMG)' - DOCKER_BUILDKIT=1 $(OCI_RUNTIME) push $(DOCKER_IMG):$(DOCKER_TAG) - -##@ kubernetes - -# note: to deploy with custom image tag use: DOCKER_TAG=test make deploy -.PHONY: deploy -deploy: ## Deploy the image - sed 's|%DOCKER_IMG%|$(DOCKER_IMG)|g;s|%DOCKER_TAG%|$(DOCKER_TAG)|g' contrib/kubernetes/deployment.yaml > /tmp/deployment.yaml - kubectl create configmap flowlogs-pipeline-configuration --from-file=flowlogs-pipeline.conf.yaml=$(FLP_CONF_FILE) - kubectl apply -f /tmp/deployment.yaml - kubectl rollout status "deploy/flowlogs-pipeline" --timeout=600s - -.PHONY: undeploy -undeploy: ## Undeploy the image - sed 's|%DOCKER_IMG%|$(DOCKER_IMG)|g;s|%DOCKER_TAG%|$(DOCKER_TAG)|g' contrib/kubernetes/deployment.yaml > /tmp/deployment.yaml - kubectl --ignore-not-found=true delete configmap flowlogs-pipeline-configuration || true - kubectl --ignore-not-found=true delete -f /tmp/deployment.yaml || true - -.PHONY: deploy-loki -deploy-loki: ## Deploy loki - kubectl apply -f contrib/kubernetes/deployment-loki-storage.yaml - kubectl apply -f contrib/kubernetes/deployment-loki.yaml - kubectl rollout status "deploy/loki" --timeout=600s - -pkill --oldest --full "3100:3100" - kubectl port-forward --address 0.0.0.0 svc/loki 3100:3100 2>&1 >/dev/null & - @echo -e "\nloki endpoint is available on http://localhost:3100\n" - -.PHONY: undeploy-loki -undeploy-loki: ## Undeploy loki - kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-loki.yaml || true - kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-loki-storage.yaml || true - -pkill --oldest --full "3100:3100" - -.PHONY: deploy-prometheus -deploy-prometheus: ## Deploy prometheus - kubectl apply -f contrib/kubernetes/deployment-prometheus.yaml - kubectl rollout status "deploy/prometheus" --timeout=600s - -pkill --oldest --full "9090:9090" - kubectl port-forward --address 0.0.0.0 svc/prometheus 9090:9090 2>&1 >/dev/null & - @echo -e "\nprometheus ui is available on http://localhost:9090\n" - -.PHONY: undeploy-prometheus -undeploy-prometheus: ## Undeploy prometheus - kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-prometheus.yaml || true - -pkill --oldest --full "9090:9090" - -.PHONY: deploy-grafana -deploy-grafana: ## Deploy grafana - kubectl create configmap grafana-dashboard-definitions --from-file=contrib/dashboards/ - kubectl apply -f contrib/kubernetes/deployment-grafana.yaml - kubectl rollout status "deploy/grafana" --timeout=600s - -pkill --oldest --full "3000:3000" - kubectl port-forward --address 0.0.0.0 svc/grafana 3000:3000 2>&1 >/dev/null & - @echo -e "\ngrafana ui is available (user: admin password: admin) on http://localhost:3000\n" - -.PHONY: undeploy-grafana -undeploy-grafana: ## Undeploy grafana - kubectl --ignore-not-found=true delete configmap grafana-dashboard-definitions || true - kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-grafana.yaml || true - -pkill --oldest --full "3000:3000" - -.PHONY: deploy-netflow-simulator -deploy-netflow-simulator: ## Deploy netflow simulator - kubectl apply -f contrib/kubernetes/deployment-netflow-simulator.yaml - kubectl rollout status "deploy/netflowsimulator" --timeout=600s - -.PHONY: undeploy-netflow-simulator -undeploy-netflow-simulator: ## Undeploy netflow simulator - kubectl --ignore-not-found=true delete -f contrib/kubernetes/deployment-netflow-simulator.yaml || true - -##@ kind - -.PHONY: create-kind-cluster -create-kind-cluster: $(KIND) ## Create cluster - $(KIND) create cluster --name $(KIND_CLUSTER_NAME) --config contrib/kubernetes/kind/kind.config.yaml - kubectl cluster-info --context kind-kind - -.PHONY: delete-kind-cluster -delete-kind-cluster: $(KIND) ## Delete cluster - $(KIND) delete cluster --name $(KIND_CLUSTER_NAME) - -.PHONY: kind-load-image -kind-load-image: ## Load image to kind -ifeq ($(OCI_RUNTIME),$(shell which docker)) -# This is an optimization for docker provider. "kind load docker-image" can load an image directly from docker's -# local registry. For other providers (i.e. podman), we must use "kind load image-archive" instead. - $(KIND) load --name $(KIND_CLUSTER_NAME) docker-image $(DOCKER_IMG):$(DOCKER_TAG) -else - $(eval tmpfile="/tmp/flp.tar") - -rm $(tmpfile) - $(OCI_RUNTIME) save $(DOCKER_IMG):$(DOCKER_TAG) -o $(tmpfile) - $(KIND) load --name $(KIND_CLUSTER_NAME) image-archive $(tmpfile) - -rm $(tmpfile) +.PHONY: ci-manifest-push +ci-manifest-push: ## Push CI manifest + $(OCI_BIN) push $(IMAGE_SHA) +ifeq ($(VERSION), main) +# Also tag "latest" only for branch "main" + $(OCI_BIN) push ${IMAGE} + $(OCI_BIN) push $(IMAGE_TAG_BASE):latest endif -##@ metrics - -.PHONY: generate-configuration -generate-configuration: $(KIND) ## Generate metrics configuration - go build "${CMD_DIR}${CG_BIN_FILE}" - ./${CG_BIN_FILE} --log-level debug --srcFolder network_definitions \ - --destConfFile $(FLP_CONF_FILE) \ - --destDocFile docs/metrics.md \ - --destGrafanaJsonnetFolder contrib/dashboards/jsonnet/ - -##@ End2End - -.PHONY: local-deployments-deploy -local-deployments-deploy: $(KIND) deploy-prometheus deploy-loki deploy-grafana build-image kind-load-image deploy deploy-netflow-simulator - kubectl get pods - kubectl rollout status -w deployment/flowlogs-pipeline - kubectl logs -l app=flowlogs-pipeline - -.PHONY: local-deploy -local-deploy: $(KIND) local-cleanup create-kind-cluster local-deployments-deploy ## Deploy locally on kind (with simulated flowlogs) - -.PHONY: local-deployments-cleanup -local-deployments-cleanup: $(KIND) undeploy-netflow-simulator undeploy undeploy-grafana undeploy-loki undeploy-prometheus - -.PHONY: local-cleanup -local-cleanup: $(KIND) local-deployments-cleanup delete-kind-cluster ## Undeploy from local kind - -.PHONY: local-redeploy -local-redeploy: local-deployments-cleanup local-deployments-deploy ## Redeploy locally (on current kind) - -.PHONY: ocp-deploy -ocp-deploy: ocp-cleanup deploy-prometheus deploy-loki deploy-grafana deploy ## Deploy to OCP - flowlogs_pipeline_svc_ip=$$(kubectl get svc flowlogs-pipeline -o jsonpath='{.spec.clusterIP}'); \ - ./hack/enable-ocp-flow-export.sh $$flowlogs_pipeline_svc_ip - kubectl get pods - kubectl rollout status -w deployment/flowlogs-pipeline - kubectl logs -l app=flowlogs-pipeline - oc expose service prometheus || true - @prometheus_url=$$(oc get route prometheus -o jsonpath='{.spec.host}'); \ - echo -e "\nAccess prometheus on OCP using: http://"$$prometheus_url"\n" - oc expose service grafana || true - @grafana_url=$$(oc get route grafana -o jsonpath='{.spec.host}'); \ - echo -e "\nAccess grafana on OCP using: http://"$$grafana_url"\n" - oc expose service loki || true - @loki_url=$$(oc get route loki -o jsonpath='{.spec.host}'); \ - echo -e "\nAccess loki on OCP using: http://"$$loki_url"\n" - -.PHONY: ocp-cleanup -ocp-cleanup: undeploy undeploy-loki undeploy-prometheus undeploy-grafana ## Undeploy from OCP - -.PHONY: dev-local-deploy -dev-local-deploy: ## Deploy locally with simulated netflows - -pkill --oldest --full "${FLP_BIN_FILE}" - -pkill --oldest --full "${NETFLOW_GENERATOR}" - go build "${CMD_DIR}${FLP_BIN_FILE}" - go build "${CMD_DIR}${CG_BIN_FILE}" - ./${CG_BIN_FILE} --log-level debug --srcFolder network_definitions \ - --skipWithTags "kubernetes" \ - --destConfFile /tmp/flowlogs-pipeline.conf.yaml --destGrafanaJsonnetFolder /tmp/ - test -f /tmp/${NETFLOW_GENERATOR} || curl -L --output /tmp/${NETFLOW_GENERATOR} https://github.com/nerdalert/nflow-generator/blob/master/binaries/nflow-generator-x86_64-linux?raw=true - chmod +x /tmp/${NETFLOW_GENERATOR} - ./"${FLP_BIN_FILE}" --config /tmp/flowlogs-pipeline.conf.yaml & - /tmp/${NETFLOW_GENERATOR} -t 127.0.0.1 -p 2056 > /dev/null 2>&1 & +include .mk/development.mk +include .mk/shortcuts.mk \ No newline at end of file diff --git a/README.md b/README.md index ed5a7c3ec..66697f344 100644 --- a/README.md +++ b/README.md @@ -899,7 +899,22 @@ The `suppressGoMetrics` parameter may be set to `true` in order to suppress the - Change directory into flowlogs-pipeline into: `cd flowlogs-pipeline` - Build the code: - `make build` + ```bash + # compile project + make build + + # build the default image (quay.io/netobserv/flowlogs-pipeline:latest): + make image-build + + # push the default image (quay.io/netobserv/flowlogs-pipeline:latest): + make image-push + + # build and push on your own quay.io account (quay.io/myuser/flowlogs-pipeline:dev): + IMAGE_ORG=myuser VERSION=dev make images + + # build and push on a different registry + IMAGE=dockerhub.io/myuser/plugin:tag make images + ``` FLP uses `Makefile` to build, tests and deploy. Following is the output of `make help` : @@ -911,6 +926,7 @@ Usage: General help Display this help. + vendors Check go vendors Develop lint Lint the code @@ -924,8 +940,13 @@ Develop benchmarks Benchmark run Run -Docker - push-image Push latest image +Images + image-build Build MULTIARCH_TARGETS images + image-push Push MULTIARCH_TARGETS images + manifest-build Build MULTIARCH_TARGETS manifest + manifest-push Push MULTIARCH_TARGETS manifest + ci-manifest-build Build CI manifest + ci-manifest-push Push CI manifest kubernetes deploy Deploy the image @@ -953,6 +974,17 @@ End2End local-redeploy Redeploy locally (on current kind) ocp-deploy Deploy to OCP ocp-cleanup Undeploy from OCP - dev-local-deploy Deploy locally with simulated netflows + dev-local-deploy Deploy locally with simulated netflows + +shortcuts helpers + build-image Build MULTIARCH_TARGETS images + push-image Push MULTIARCH_TARGETS images + build-manifest Build MULTIARCH_TARGETS manifest + push-manifest Push MULTIARCH_TARGETS manifest + images Build and push MULTIARCH_TARGETS images and related manifest + build-ci-manifest Build CI manifest + push-ci-manifest Push CI manifest + ci-manifest Build and push CI manifest + ci Build and push CI images and manifest ``` diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 4b3e55771..c3b45031f 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -11,6 +11,7 @@ WORKDIR /app COPY go.mod . COPY go.sum . COPY Makefile . +COPY .mk/ .mk/ COPY .bingo/ .bingo/ COPY vendor/ vendor/ COPY .git/ .git/ diff --git a/contrib/kubernetes/deployment.yaml b/contrib/kubernetes/deployment.yaml index c49cfaadd..b926bf5ac 100644 --- a/contrib/kubernetes/deployment.yaml +++ b/contrib/kubernetes/deployment.yaml @@ -16,7 +16,7 @@ spec: spec: containers: - name: flowlogs-pipeline - image: %DOCKER_IMG%:%DOCKER_TAG% + image: %IMAGE_TAG_BASE%:%VERSION% args: - "--config=/etc/flowlogs-pipeline/flowlogs-pipeline.conf.yaml" ports: diff --git a/pkg/test/e2e/kafka/flp.yaml b/pkg/test/e2e/kafka/flp.yaml index 92ed9bfb7..970ea7edb 100644 --- a/pkg/test/e2e/kafka/flp.yaml +++ b/pkg/test/e2e/kafka/flp.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: flowlogs-pipeline - image: quay.io/netobserv/flowlogs-pipeline:e2e + image: quay.io/netobserv/flowlogs-pipeline:e2e-amd64 args: - "--config=/etc/flowlogs-pipeline/flowlogs-pipeline.conf.yaml" ports: diff --git a/pkg/test/e2e/pipline/flp.yaml b/pkg/test/e2e/pipline/flp.yaml index 92ed9bfb7..970ea7edb 100644 --- a/pkg/test/e2e/pipline/flp.yaml +++ b/pkg/test/e2e/pipline/flp.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: flowlogs-pipeline - image: quay.io/netobserv/flowlogs-pipeline:e2e + image: quay.io/netobserv/flowlogs-pipeline:e2e-amd64 args: - "--config=/etc/flowlogs-pipeline/flowlogs-pipeline.conf.yaml" ports: diff --git a/pkg/test/e2e/utils.go b/pkg/test/e2e/utils.go index 2921479b8..075f4b4dd 100644 --- a/pkg/test/e2e/utils.go +++ b/pkg/test/e2e/utils.go @@ -56,12 +56,13 @@ func Main(m *testing.M, manifestDeployDefinitions ManifestDeployDefinitions, tes *testEnv = env.New() kindClusterName := "test" namespace := "default" - dockerImage := "quay.io/netobserv/flowlogs-pipeline" - dockerTag := "e2e" + org := "netobserv" + version := "e2e" + arch := "amd64" (*testEnv).Setup( e2eRecreateKindCluster(kindClusterName), - e2eBuildAndLoadImageIntoKind(dockerImage, dockerTag, kindClusterName), + e2eBuildAndLoadImageIntoKind(org, version, arch, kindClusterName), e2eRecreateNamespace(namespace), e2eDeployEnvironmentResources(manifestDeployDefinitions, namespace), ) @@ -91,12 +92,12 @@ func e2eDeleteKindCluster(clusterName string) env.Func { } } -func e2eBuildAndLoadImageIntoKind(dockerImg, dockerTag, clusterName string) env.Func { +func e2eBuildAndLoadImageIntoKind(org, version, arch, clusterName string) env.Func { return func(ctx context.Context, cfg *envconf.Config) (context.Context, error) { e := gexe.New() - fmt.Printf("====> building docker image - %s:%s\n", dockerImg, dockerTag) - p := e.RunProc(fmt.Sprintf(`/bin/sh -c "cd $(git rev-parse --show-toplevel); DOCKER_IMG=%s DOCKER_TAG=%s KIND_CLUSTER_NAME=%s make build-image kind-load-image"`, - dockerImg, dockerTag, clusterName)) + fmt.Printf("====> building docker image - %s:%s\n", org, version) + p := e.RunProc(fmt.Sprintf(`/bin/sh -c "cd $(git rev-parse --show-toplevel); MULTIARCH_TARGETS=%s IMAGE_ORG=%s VERSION=%s KIND_CLUSTER_NAME=%s make image-build kind-load-image"`, + arch, org, version, clusterName)) if p.Err() != nil || !p.IsSuccess() || p.ExitCode() != 0 { return nil, fmt.Errorf("failed to build or load docker image err=%v result=%v", p.Err(), p.Result()) }