diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..526c8a38 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml deleted file mode 100644 index f29c6d17..00000000 --- a/.github/release-drafter.yml +++ /dev/null @@ -1,21 +0,0 @@ -name-template: 'v$NEXT_PATCH_VERSION' -tag-template: 'v$NEXT_PATCH_VERSION' -categories: - - title: '🚀 Added' - label: 'added-feature' - - title: '🧰 Changed' - label: 'changed' - - title: "⚠️ Deprecated" - label: "deprecated" - - title: "⚠️ Removed" - label: "removed" - - title: '🐛 Bug Fixes' - label: 'bugfix' - - title: "⚠️ Security" - label: "security" -change-template: '- $TITLE @$AUTHOR (#$NUMBER)' -no-changes-template: "- No changes" -template: | - ## Changes - - $CHANGES diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..ec270e93 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,55 @@ +name: Continuous Integration +on: + workflow_dispatch: null + push: + branches: + - main + pull_request: null + +jobs: + ci: + runs-on: ubuntu-latest + strategy: + matrix: + go-version: [ 'stable', 'oldstable' ] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go-version }} + - name: Vet + run: make vet + - name: Lint + run: make lint + - name: Helm Lint + run: make helm-lint + - name: Test + run: make test + - name: Build + run: make build + docker-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Docker Meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + linode/linode-cloud-controller-manager + tags: | + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} + type=semver,pattern={{raw}},value=${{ github.ref_name }} + - name: Build Dockerfile + uses: docker/build-push-action@v5 + with: + context: . + push: false + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + build-args: | + REV=${{ github.ref_name }} diff --git a/.github/workflows/docker-hub.yml b/.github/workflows/docker-hub.yml deleted file mode 100644 index 45b58b26..00000000 --- a/.github/workflows/docker-hub.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Publish Docker Release -on: - release: - types: [ published ] -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@61b9e3751b92087fd0b06925ba6dd6314e06f089 # pin@master - - name: Build - run: make build-linux - - name: Publish latest to Registry - uses: elgohr/Publish-Docker-Github-Action@13c6c46d98bc92e6c046454248cd28630400846a # pin@master - with: - name: linode/linode-cloud-controller-manager - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - tags: "latest,${{ github.event.release.tag_name }}" diff --git a/.github/workflows/label-sync.yml b/.github/workflows/label-sync.yml index df229fc0..9b097ecf 100644 --- a/.github/workflows/label-sync.yml +++ b/.github/workflows/label-sync.yml @@ -2,7 +2,7 @@ name: Sync labels on: push: branches: - - master + - main paths: - .github/labels.yml jobs: diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml deleted file mode 100644 index 9e097236..00000000 --- a/.github/workflows/release-drafter.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: Release Drafter - -on: - push: - branches: - - master - -jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - - uses: release-drafter/release-drafter@fe52e97d262833ae07d05efaf1a239df3f1b5cd4 # pin@v5 - with: - config-name: release-drafter.yml - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..bb27f50d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,43 @@ +name: Release +on: + push: + tags: + - "v*.*.*" + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Create Release Artifacts + run: make release + env: + IMAGE_VERSION: ${{ github.ref_name }} + - name: Upload Release Artifacts + uses: softprops/action-gh-release@v1 + with: + files: | + ./release/helm-chart-${{ github.ref_name }}.tgz + - name: Docker Meta + id: meta + uses: docker/metadata-action@v5 + with: + images: | + linode/linode-cloud-controller-manager + tags: | + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }} + type=semver,pattern={{raw}},value=${{ github.ref_name }} + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build and Push to Docker Hub + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index fe60f0a4..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Test -on: - push: - branches: - - master - pull_request: -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v2 - - name: lint - run: make lint - - name: build - run: make docker-build - - name: unit test - run: make test - - name: helm lint - run: make helm-lint - - name: helm template - run: make helm-template \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index b9a41d20..20942766 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,19 @@ -# NB: We now cross-compile the go binary locally using the Makefile -FROM alpine:latest -RUN apk update && apk add ca-certificates && rm -rf /var/cache/apk/* -COPY dist/linode-cloud-controller-manager-linux-amd64 / -ENTRYPOINT ["/linode-cloud-controller-manager-linux-amd64"] +FROM golang:1.21-alpine as builder +RUN mkdir -p /linode +WORKDIR /linode + +COPY go.mod . +COPY go.sum . +COPY main.go . +COPY cloud ./cloud +COPY sentry ./sentry + +RUN go mod download +RUN go build -a -ldflags '-extldflags "-static"' -o /bin/linode-cloud-controller-manager-linux /linode + +FROM alpine:3.18.4 +RUN apk add --update --no-cache ca-certificates +LABEL maintainers="Linode" +LABEL description="Linode Cloud Controller Manager" +COPY --from=builder /bin/linode-cloud-controller-manager-linux /linode-cloud-controller-manager-linux +ENTRYPOINT ["/linode-cloud-controller-manager-linux"] diff --git a/Makefile b/Makefile index b37d96fb..7aad51d1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ IMG ?= linode/linode-cloud-controller-manager:canary +RELEASE_DIR ?= release +GOLANGCI_LINT_IMG := golangci/golangci-lint:v1.55-alpine export GO111MODULE=on @@ -7,13 +9,19 @@ all: build .PHONY: clean clean: - go clean . - rm -r dist/* + @go clean . + @rm -rf ./.tmp + @rm -rf dist/* + @rm -rf $(RELEASE_DIR) .PHONY: codegen codegen: go generate ./... +.PHONY: vet +vet: fmt + go vet ./... + .PHONY: lint lint: docker run --rm -v "$(shell pwd):/var/work:ro" -w /var/work \ @@ -43,6 +51,12 @@ build: codegen CGO_ENABLED=0 \ go build -o dist/linode-cloud-controller-manager . +.PHONY: release +release: + mkdir -p $(RELEASE_DIR) + sed -e 's/appVersion: "latest"/appVersion: "$(IMAGE_VERSION)"/g' ./deploy/chart/Chart.yaml + tar -czvf ./$(RELEASE_DIR)/helm-chart-$(IMAGE_VERSION).tgz -C ./deploy/chart . + .PHONY: imgname # print the Docker image name that will be used # useful for subsequently defining it on the shell diff --git a/README.md b/README.md index b6d364b4..18204c65 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ [![Twitter](https://img.shields.io/twitter/follow/linode.svg?style=social&logo=twitter&label=Follow)](https://twitter.com/intent/follow?screen_name=linode) ## The purpose of the CCM - The Linode Cloud Controller Manager (CCM) creates a fully supported Kubernetes experience on Linode. @@ -25,17 +24,14 @@ allowing pods to be appropriately rescheduled. failure domains. ## Kubernetes Supported Versions - Kubernetes 1.9+ ## Usage ### LoadBalancer Services - Kubernetes Services of type `LoadBalancer` will be served through a [Linode NodeBalancer](https://www.linode.com/nodebalancers) which the Cloud Controller Manager will provision on demand. For general feature and usage notes, refer to the [Getting Started with Linode NodeBalancers](https://www.linode.com/docs/platform/nodebalancer/getting-started-with-nodebalancers/) guide. #### Annotations - The Linode CCM accepts several annotations which affect the properties of the underlying NodeBalancer deployment. All of the Service annotation names listed below have been shortened for readability. The values, such as `http`, are case-sensitive. @@ -63,7 +59,6 @@ Annotation (Suffix) | Values | Default | Description `firewall-id` | string | | The Firewall ID that's applied to the NodeBalancer instance. #### Deprecated Annotations - These annotations are deprecated, and will be removed in a future release. Annotation (Suffix) | Values | Default | Description | Scheduled Removal @@ -71,11 +66,9 @@ Annotation (Suffix) | Values | Default | Description | Scheduled Removal `proxy-protcol` | `none`, `v1`, `v2` | `none` | Specifies whether to use a version of Proxy Protocol on the underlying NodeBalancer | Q4 2021 #### Annotation bool values - For annotations with bool value types, `"1"`, `"t"`, `"T"`, `"True"`, `"true"` and `"True"` are valid string representations of `true`. Any other values will be interpreted as false. For more details, see [strconv.ParseBool](https://golang.org/pkg/strconv/#ParseBool). #### Port Specific Configuration - These configuration options can be specified via the `port-*` annotation, encoded in JSON. Key | Values | Default | Description @@ -85,7 +78,6 @@ Key | Values | Default | Description `tls-secret-name` | string | | Specifies a secret to use for TLS. The secret type should be `kubernetes.io/tls`. ### Nodes - Kubernetes Nodes can be configured with the following annotations. Each *Node* annotation **MUST** be prefixed with:
@@ -101,7 +93,6 @@ Key | Values | Default | Description [VPC]: https://www.linode.com/blog/linode/new-betas-coming-to-green-light/ ### Example usage - ```yaml kind: Service apiVersion: v1 @@ -160,12 +151,10 @@ spec: See more in the [examples directory](examples) ## Why `stickiness` and `algorithm` annotations don't exist - As kube-proxy will simply double-hop the traffic to a random backend Pod anyway, it doesn't matter which backend Node traffic is forwarded-to for the sake of session stickiness. These annotations are not necessary to implement session stickiness, as kube-proxy will simply double-hop the packets to a random backend Pod. It would not make a difference to set a backend Node that would receive the network traffic in an attempt to set session stickiness. ## How to use sessionAffinity - In Kubernetes, sessionAffinity refers to a mechanism that allows a client always to be redirected to the same pod when the client hits a service. To enable sessionAffinity `service.spec.sessionAffinity` field must be set to `ClientIP` as the following service yaml: @@ -194,7 +183,6 @@ sessionAffinityConfig: ``` ## Generating a Manifest for Deployment - Use the script located at `./deploy/generate-manifest.sh` to generate a self-contained deployment manifest for the Linode CCM. Two arguments are required. The first argument must be a Linode APIv4 Personal Access Token with all permissions. @@ -216,7 +204,6 @@ This will create a file `ccm-linode.yaml` which you can use to deploy the CCM. Note: Your kubelets, controller-manager, and apiserver must be started with `--cloud-provider=external` as noted in the following documentation. ## Deployment Through Helm Chart - Use the helm chart located under './deploy/chart'. This dir has the manifest for Linode CCM. There are two arguments required. The first argument must be a Linode APIv4 [Personal Access Token](https://cloud.linode.com/profile/tokens) with all permissions. @@ -225,44 +212,40 @@ The second argument must be a Linode [region](https://api.linode.com/v4/regions) ### To deploy CCM run the following helm command once you are in the ccm root dir: ```sh -git clone https://github.com/linode/linode-cloud-controller-manager.git - -cd linode-cloud-controller-manager - -helm install linode-ccm ./deploy/chart --set apiToken=$LINODE_API_TOKEN,region=$REGION +export VERSION=v0.3.22 +export LINODE_API_TOKEN= +export REGION= +helm install linode-ccm --set apiToken=$LINODE_API_TOKEN,region=$REGION https://github.com/linode/linode-cloud-controller-manager/releases/download/$VERSION/helm-chart-$VERSION.tgz ``` _See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._ ### To uninstall linode-ccm from kubernetes cluster. Run the following command: ```sh - helm uninstall linode-ccm - ``` _See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._ ### To upgrade when new changes are made to the helm chart. Run the following command: ```sh +export VERSION=v0.3.22 +export LINODE_API_TOKEN= +export REGION= -helm upgrade linode-ccm ./deploy/chart --install - +helm upgrade linode-ccm --install --set apiToken=$LINODE_API_TOKEN,region=$REGION https://github.com/linode/linode-cloud-controller-manager/releases/download/$VERSION/helm-chart-$VERSION.tgz ``` _See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._ ### Configurations - There are other variables that can be set to a different value. For list of all the modifiable variables/values, take a look at './deploy/chart/values.yaml'. Values can be set/overrided by using the '--set var=value,...' flag or by passing in a custom-values.yaml using '-f custom-values.yaml'. Recommendation: Use custom-values.yaml to override the variables to avoid any errors with template rendering - ### Upstream Documentation Including Deployment Instructions [Kubernetes Cloud Controller Manager](https://kubernetes.io/docs/tasks/administer-cluster/running-cloud-controller/). - ## Upstream Developer Documentation [Developing a Cloud Controller Manager](https://kubernetes.io/docs/tasks/administer-cluster/developing-cloud-controller-manager/). @@ -297,7 +280,6 @@ cd $(go env GOPATH)/src/github.com/linode/linode-cloud-controller-manager ``` #### Install Dev tools - To install various dev tools for Pharm Controller Manager, run the following command: ```bash @@ -305,7 +287,6 @@ To install various dev tools for Pharm Controller Manager, run the following com ``` #### Build Binary - Use the following Make targets to build and run a local binary ```bash @@ -316,7 +297,6 @@ $ dist/linode-cloud-controller-manager ``` #### Dependency management - Linode Cloud Controller Manager uses [Go Modules](https://blog.golang.org/using-go-modules) to manage dependencies. If you want to update/add dependencies, run: @@ -325,7 +305,6 @@ go mod tidy ``` #### Building Docker images - To build and push a Docker image, use the following make targets. ```bash @@ -344,9 +323,7 @@ docker run -ti linode/linode-cloud-controller-manager:canary ``` ## Contribution Guidelines - Want to improve the linode-cloud-controller-manager? Please start [here](.github/CONTRIBUTING.md). ## Join the Kubernetes Community - For general help or discussion, join us in #linode on the [Kubernetes Slack](https://kubernetes.slack.com/messages/CD4B15LUR/details/). To sign up, use the [Kubernetes Slack inviter](http://slack.kubernetes.io/). diff --git a/deploy/chart/Chart.yaml b/deploy/chart/Chart.yaml index 74139165..c442b685 100644 --- a/deploy/chart/Chart.yaml +++ b/deploy/chart/Chart.yaml @@ -3,4 +3,4 @@ name: ccm-linode description: The Linode Cloud Controller Manager (CCM) provides a way for Kubernetes clusters to access additional Linode services. Linode's CCM will automatically provision a Linode NodeBalancer for Kubernetes Services of type "LoadBalancer". type: application version: 1.0.0 -appVersion: "v0.3.16" +appVersion: "latest" diff --git a/go.mod b/go.mod index 28de6222..d71fa7c0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/linode/linode-cloud-controller-manager -go 1.17 +go 1.20 require ( github.com/appscode/go v0.0.0-20200323182826-54e98e09185a diff --git a/go.sum b/go.sum index 32e47edc..01f9b50d 100644 --- a/go.sum +++ b/go.sum @@ -72,7 +72,6 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= diff --git a/main.go b/main.go index e433dde4..496c403c 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,9 @@ package main import ( "context" - goflag "flag" + "flag" "fmt" - "math/rand" "os" - "time" "github.com/linode/linode-cloud-controller-manager/cloud/linode" "github.com/linode/linode-cloud-controller-manager/sentry" @@ -18,9 +16,10 @@ import ( "k8s.io/cloud-provider/options" utilflag "k8s.io/component-base/cli/flag" "k8s.io/component-base/logs" + "k8s.io/klog" + _ "k8s.io/component-base/metrics/prometheus/clientgo" // for client metric registration _ "k8s.io/component-base/metrics/prometheus/version" // for version metric registration - "k8s.io/klog" ) const ( @@ -67,8 +66,6 @@ func main() { ctx := sentry.SetHubOnContext(context.Background()) - rand.Seed(time.Now().UTC().UnixNano()) - ccmOptions, err := options.NewCloudControllerManagerOptions() if err != nil { klog.Fatalf("unable to initialize command options: %v", err) @@ -111,7 +108,7 @@ func main() { } pflag.CommandLine.SetNormalizeFunc(utilflag.WordSepNormalizeFunc) - pflag.CommandLine.AddGoFlagSet(goflag.CommandLine) + pflag.CommandLine.AddGoFlagSet(flag.CommandLine) logs.InitLogs() defer logs.FlushLogs()