Skip to content

Commit 8b6192e

Browse files
committed
docs: rewrite README, add helm chart, examples, clean up boilerplate
- README rewritten in layman's terms with quickstart, PivotIP reference, helm install from ghcr, and first-IP-in-5-minutes inline example - config/samples filled with real fields - examples/nginx-floating-ip/ added (deployment, service, pivotip) - charts/oci-pivot-controller/ helm chart added - release.yml: trigger on release event, native arm64 runners, helm OCI push to ghcr.io/syscode-labs/charts, make-public job for packages - IMG default updated to ghcr.io/syscode-labs/oci-pivot-controller:latest - Removed all kubebuilder TODO boilerplate comments - pre-commit: exclude helm templates from check-yaml, allow multi-doc YAML
1 parent c1a562a commit 8b6192e

21 files changed

Lines changed: 461 additions & 116 deletions

File tree

.github/workflows/release.yml

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: Release
22

33
on:
4+
release:
5+
types: [published]
46
workflow_dispatch:
57
inputs:
68
tag:
@@ -15,6 +17,7 @@ env:
1517
jobs:
1618
build-push:
1719
strategy:
20+
fail-fast: false
1821
matrix:
1922
include:
2023
- arch: amd64
@@ -36,13 +39,16 @@ jobs:
3639
username: ${{ github.actor }}
3740
password: ${{ secrets.GITHUB_TOKEN }}
3841

42+
- name: Build context note
43+
run: echo "::notice title=Build context::Building linux/${{ matrix.arch }} on native runner ${{ matrix.runner }}."
44+
3945
- uses: docker/build-push-action@v6
4046
with:
4147
context: .
4248
platforms: linux/${{ matrix.arch }}
4349
push: true
4450
tags: |
45-
${{ env.IMAGE }}:${{ inputs.tag }}-${{ matrix.arch }}
51+
${{ env.IMAGE }}:${{ github.event.release.tag_name || inputs.tag }}-${{ matrix.arch }}
4652
${{ env.IMAGE }}:latest-${{ matrix.arch }}
4753
4854
merge-manifests:
@@ -51,19 +57,70 @@ jobs:
5157
permissions:
5258
packages: write
5359
steps:
60+
- uses: docker/setup-buildx-action@v3
61+
5462
- uses: docker/login-action@v4
5563
with:
5664
registry: ${{ env.REGISTRY }}
5765
username: ${{ github.actor }}
5866
password: ${{ secrets.GITHUB_TOKEN }}
5967

6068
- name: Create multi-arch manifests
69+
shell: bash
6170
run: |
71+
set -euo pipefail
72+
TAG="${{ github.event.release.tag_name || inputs.tag }}"
73+
6274
docker buildx imagetools create \
63-
-t ${{ env.IMAGE }}:${{ inputs.tag }} \
64-
${{ env.IMAGE }}:${{ inputs.tag }}-amd64 \
65-
${{ env.IMAGE }}:${{ inputs.tag }}-arm64
75+
-t ${{ env.IMAGE }}:${TAG} \
76+
${{ env.IMAGE }}:${TAG}-amd64 \
77+
${{ env.IMAGE }}:${TAG}-arm64
78+
6679
docker buildx imagetools create \
6780
-t ${{ env.IMAGE }}:latest \
6881
${{ env.IMAGE }}:latest-amd64 \
6982
${{ env.IMAGE }}:latest-arm64
83+
84+
make-public:
85+
needs: merge-manifests
86+
runs-on: ubuntu-24.04
87+
permissions:
88+
packages: write
89+
steps:
90+
- name: Make packages public
91+
run: |
92+
gh api --method PATCH \
93+
/orgs/syscode-labs/packages/container/oci-pivot-controller \
94+
-f visibility=public
95+
gh api --method PATCH \
96+
/orgs/syscode-labs/packages/container/charts%2Foci-pivot-controller \
97+
-f visibility=public
98+
env:
99+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
100+
101+
release-helm:
102+
needs: merge-manifests
103+
runs-on: ubuntu-24.04
104+
permissions:
105+
packages: write
106+
steps:
107+
- uses: actions/checkout@v4
108+
109+
- uses: azure/setup-helm@v4
110+
111+
- name: Log in to GHCR (Helm)
112+
run: helm registry login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
113+
114+
- name: Package and push Helm chart
115+
shell: bash
116+
run: |
117+
set -euo pipefail
118+
TAG="${{ github.event.release.tag_name || inputs.tag }}"
119+
CHART_VERSION="${TAG#v}"
120+
121+
helm package charts/oci-pivot-controller \
122+
--version "${CHART_VERSION}" \
123+
--app-version "${TAG}"
124+
125+
helm push "oci-pivot-controller-${CHART_VERSION}.tgz" \
126+
oci://ghcr.io/syscode-labs/charts

.pre-commit-config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ repos:
55
- id: trailing-whitespace
66
- id: end-of-file-fixer
77
- id: check-yaml
8+
args: [--allow-multiple-documents]
9+
exclude: ^charts/.*templates/
810
- id: check-json
911
- id: mixed-line-ending
1012

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Image URL to use all building/pushing image targets
2-
IMG ?= controller:latest
2+
IMG ?= ghcr.io/syscode-labs/oci-pivot-controller:latest
33

44
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
55
ifeq (,$(shell go env GOBIN))
@@ -61,8 +61,7 @@ vet: ## Run go vet against code.
6161
test: manifests generate fmt vet setup-envtest ## Run tests.
6262
KUBEBUILDER_ASSETS="$(shell "$(ENVTEST)" use $(ENVTEST_K8S_VERSION) --bin-dir "$(LOCALBIN)" -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
6363

64-
# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'.
65-
# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally.
64+
# The default e2e setup uses Kind with the Manager Docker image loaded locally.
6665
# CertManager is installed by default; skip with:
6766
# - CERT_MANAGER_INSTALL_SKIP=true
6867
KIND_CLUSTER ?= oci-pivot-controller-test-e2e

README.md

Lines changed: 103 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,151 @@
11
# oci-pivot-controller
2-
// TODO(user): Add simple overview of use/purpose
32

4-
## Description
5-
// TODO(user): An in-depth paragraph about your project and overview of use
3+
[![CI](https://github.com/syscode-labs/oci-pivot-controller/actions/workflows/ci.yml/badge.svg)](https://github.com/syscode-labs/oci-pivot-controller/actions/workflows/ci.yml)
4+
[![CodeQL](https://github.com/syscode-labs/oci-pivot-controller/actions/workflows/codeql.yml/badge.svg)](https://github.com/syscode-labs/oci-pivot-controller/actions/workflows/codeql.yml)
5+
[![Go Version](https://img.shields.io/badge/go-1.25-00ADD8?logo=go)](https://go.dev/doc/devel/release)
6+
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
67

7-
## Getting Started
8+
**oci-pivot-controller is a Kubernetes controller that gives your cluster a stable floating public IP on OCI — and automatically moves it to a healthy node if the current one goes down.**
89

9-
### Prerequisites
10-
- go version v1.24.6+
11-
- docker version 17.03+.
12-
- kubectl version v1.11.3+.
13-
- Access to a Kubernetes v1.11.3+ cluster.
10+
In plain terms: you create a `PivotIP` resource pointing at a Service, and the controller reserves a real OCI public IP address and wires it up so traffic reaches your app. If the node holding that IP becomes unhealthy, the controller detects it, picks a better node, and re-routes traffic — without you doing anything. The IP address never changes.
1411

15-
### To Deploy on the cluster
16-
**Build and push your image to the location specified by `IMG`:**
12+
It works entirely through OCI's native networking (secondary private IPs + reserved public IPs). No load balancer, no cloud provider integration, no CNI changes required.
1713

18-
```sh
19-
make docker-build docker-push IMG=<some-registry>/oci-pivot-controller:tag
20-
```
14+
## What It Manages
2115

22-
**NOTE:** This image ought to be published in the personal registry you specified.
23-
And it is required to have access to pull the image from the working environment.
24-
Make sure you have the proper permission to the registry if the above commands don’t work.
16+
- `PivotIP`: assigns and maintains a floating OCI reserved public IP for a Kubernetes Service
2517

26-
**Install the CRDs into the cluster:**
18+
## How It Works
2719

28-
```sh
29-
make install
30-
```
20+
1. You create a `PivotIP` pointing at a Service.
21+
2. The controller picks the healthiest node (fewest existing assignments, must be Ready).
22+
3. It creates a secondary private IP on that node's VNIC and attaches a reserved OCI public IP to it.
23+
4. It sets `Service.spec.externalIPs` so the node intercepts and routes inbound traffic to your pods.
24+
5. When the node becomes unhealthy, the controller moves the secondary private IP to a new node and reassigns the public IP — the address stays the same.
3125

32-
**Deploy the Manager to the cluster with the image specified by `IMG`:**
26+
## Prerequisites
3327

34-
```sh
35-
make deploy IMG=<some-registry>/oci-pivot-controller:tag
36-
```
28+
- Kubernetes cluster running on OCI Compute instances (Ampere A1 or x86)
29+
- OCI IAM policy granting the controller permission to manage private and public IPs (see below)
30+
- `helm` (recommended) or `kubectl`
3731

38-
> **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin
39-
privileges or be logged in as admin.
32+
### Required OCI IAM Policy
4033

41-
**Create instances of your solution**
42-
You can apply the samples (examples) from the config/sample:
34+
The controller uses [instance principal authentication](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm) — no API key needed. Add this policy to the dynamic group that contains your cluster nodes:
4335

44-
```sh
45-
kubectl apply -k config/samples/
36+
```
37+
Allow dynamic-group <your-node-group> to manage private-ips in compartment <your-compartment>
38+
Allow dynamic-group <your-node-group> to manage public-ips in compartment <your-compartment>
4639
```
4740

48-
>**NOTE**: Ensure that the samples has default values to test it out.
41+
## Quickstart
4942

50-
### To Uninstall
51-
**Delete the instances (CRs) from the cluster:**
43+
### Install with Helm (Recommended)
5244

5345
```sh
54-
kubectl delete -k config/samples/
46+
helm upgrade --install oci-pivot-controller \
47+
oci://ghcr.io/syscode-labs/charts/oci-pivot-controller \
48+
--version <version> \
49+
-n oci-pivot-system --create-namespace \
50+
--set oci.compartmentId=ocid1.compartment.oc1..example
51+
52+
kubectl -n oci-pivot-system get pods
5553
```
5654

57-
**Delete the APIs(CRDs) from the cluster:**
55+
### Install with Kustomize
5856

5957
```sh
60-
make uninstall
58+
make install
59+
make deploy IMG=ghcr.io/syscode-labs/oci-pivot-controller:<tag>
6160
```
6261

63-
**UnDeploy the controller from the cluster:**
62+
### Uninstall
6463

6564
```sh
66-
make undeploy
65+
helm uninstall oci-pivot-controller -n oci-pivot-system
66+
# or (kustomize path)
67+
make undeploy && make uninstall
6768
```
6869

69-
## Project Distribution
70-
71-
Following the options to release and provide this solution to the users.
70+
## First Floating IP in 5 Minutes
7271

73-
### By providing a bundle with all YAML files
74-
75-
1. Build the installer for the image built and published in the registry:
72+
Create a Service and a PivotIP in the `default` namespace:
7673

7774
```sh
78-
make build-installer IMG=<some-registry>/oci-pivot-controller:tag
75+
kubectl apply -f - <<'EOF'
76+
apiVersion: v1
77+
kind: Service
78+
metadata:
79+
name: my-app
80+
namespace: default
81+
spec:
82+
selector:
83+
app: my-app
84+
ports:
85+
- port: 80
86+
targetPort: 8080
87+
---
88+
apiVersion: pivot.oci.io/v1alpha1
89+
kind: PivotIP
90+
metadata:
91+
name: my-app-ip
92+
namespace: default
93+
spec:
94+
serviceRef:
95+
name: my-app
96+
EOF
7997
```
8098

81-
**NOTE:** The makefile target mentioned above generates an 'install.yaml'
82-
file in the dist directory. This file contains all the resources built
83-
with Kustomize, which are necessary to install this project without its
84-
dependencies.
85-
86-
2. Using the installer
87-
88-
Users can just run 'kubectl apply -f <URL for YAML BUNDLE>' to install
89-
the project, i.e.:
99+
Check status:
90100

91101
```sh
92-
kubectl apply -f https://raw.githubusercontent.com/<org>/oci-pivot-controller/<tag or branch>/dist/install.yaml
93-
```
94-
95-
### By providing a Helm Chart
102+
kubectl get pivotip -n default
103+
# NAME PUBLIC IP NODE SERVICE AGE
104+
# my-app-ip 1.2.3.4 node-worker1 my-app 30s
96105

97-
1. Build the chart using the optional helm plugin
106+
kubectl describe pivotip my-app-ip -n default
107+
```
98108

99-
```sh
100-
kubebuilder edit --plugins=helm/v2-alpha
109+
The `PUBLIC IP` column shows the OCI reserved public IP. Traffic to that address on port 80 reaches your app pods via the elected node.
110+
111+
## PivotIP Reference
112+
113+
```yaml
114+
apiVersion: pivot.oci.io/v1alpha1
115+
kind: PivotIP
116+
metadata:
117+
name: my-app-ip
118+
namespace: default
119+
spec:
120+
# Service in the same namespace to attach the floating IP to. Required.
121+
serviceRef:
122+
name: my-app
123+
124+
# Only nodes matching these labels are eligible to hold the IP.
125+
# If omitted, all Ready nodes are eligible.
126+
nodeSelector:
127+
topology.kubernetes.io/zone: uk-london-1-ad-1
128+
129+
# OCI compartment OCID for creating IP resources.
130+
# Defaults to the --compartment-id flag set on the controller.
131+
compartmentId: ocid1.compartment.oc1..example
101132
```
102133
103-
2. See that a chart was generated under 'dist/chart', and users
104-
can obtain this solution from there.
134+
## Examples
135+
136+
See [`examples/`](examples/) for complete real-world use cases:
105137

106-
**NOTE:** If you change the project, you need to update the Helm Chart
107-
using the same command above to sync the latest changes. Furthermore,
108-
if you create webhooks, you need to use the above command with
109-
the '--force' flag and manually ensure that any custom configuration
110-
previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml'
111-
is manually re-applied afterwards.
138+
- [`examples/nginx-floating-ip/`](examples/nginx-floating-ip/) — Nginx exposed with a floating public IP, zone-pinned to a specific availability domain
112139

113140
## Contributing
114-
// TODO(user): Add detailed information on how you would like others to contribute to this project
115141

116-
**NOTE:** Run `make help` for more information on all potential `make` targets
142+
Pull requests welcome. Run `make help` for all available targets.
117143

118-
More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html)
144+
```sh
145+
make test # run unit + integration tests
146+
make lint # lint
147+
make build # compile
148+
```
119149

120150
## License
121151

@@ -132,4 +162,3 @@ distributed under the License is distributed on an "AS IS" BASIS,
132162
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133163
See the License for the specific language governing permissions and
134164
limitations under the License.
135-
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
apiVersion: v2
2+
name: oci-pivot-controller
3+
description: Kubernetes controller for floating OCI public IPs — automatically moves reserved public IPs to healthy nodes
4+
type: application
5+
version: 0.1.0
6+
appVersion: "0.1.0"
7+
keywords:
8+
- oci
9+
- floating-ip
10+
- kubernetes
11+
- controller
12+
home: https://github.com/syscode-labs/oci-pivot-controller

0 commit comments

Comments
 (0)