Unverified Commit 3f4b9090 authored by Jun Wang's avatar Jun Wang Committed by GitHub
Browse files

Bump whereabouts version to 0.5.1 (#3815)

Showing with 825 additions and 0 deletions
+825 -0
FROM golang:1.15
RUN mkdir -p $GOPATH/src/github.com/k8snetworkplumbingwg/whereabouts
WORKDIR $GOPATH/src/github.com/k8snetworkplumbingwg/whereabouts
RUN git clone -b v0.5.1 --single-branch https://github.com/k8snetworkplumbingwg/whereabouts.git .
RUN CGO_ENABLED=0 go build -o bin/whereabouts cmd/whereabouts.go
RUN CGO_ENABLED=0 go build -o bin/ip-reconciler cmd/reconciler/*.go
# Use distroless base image with debug tag, as we need to run install-cni.sh shell scripts here.
FROM gcr.io/distroless/base:debug
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/whereabouts .
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/ip-reconciler .
COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/script/install-cni.sh .
CMD ["/install-cni.sh"]
# Whereabouts Package
This package provides the ability to assign IP addresses dynamically across your Kubernetes cluster using a CNI IPAM plugin named [whereabouts](https://github.com/k8snetworkplumbingwg/whereabouts).
## Components
* Whereabouts Custom Resources
* Whereabouts DaemonSet
* Whereabouts ServiceAccount
* Whereabouts ClusterRoleBinding
* Whereabouts ip-reconciler Cronjob
## Configuration
The following configuration values can be set to customize the whereabouts installation.
### Global
| Value | Required/Optional | Description |
|-------|-------------------|-------------|
| `namespace` | Optional | The namespace in which to deploy whereabouts components. Default: kube-system |
### whereabouts Configuration
| Value | Required/Optional | Description |
|-------|-------------------|-------------|
| `whereabouts.config.resources.limits.cpu` | Optional | The limits for CPU resources of whereabouts DeamonSet |
| `whereabouts.config.resources.limits.memory` | Optional | The limits for memory resources of whereabouts DeamonSet |
| `whereabouts.config.resources.requests.cpu` | Optional | The requests for CPU resources of whereabouts DeamonSet |
| `whereabouts.config.resources.requests.memory` | Optional | The requests for memory resources of whereabouts DeamonSet |
| `ip_reconciler.config.schedule` | Optional | The schedule of ip-reconciler CronJob. Default: \*/5 \* \* \* \* |
| `ip_reconciler.config.resources.requests.cpu` | Optional | The requests for memory resources of ip-reconciler CronJob |
| `ip_reconciler.config.resources.requests.memory` | Optional | The requests for memory resources of ip-reconciler CronJob |
## Usage
The follow is a basic guide for getting started with whereabouts.
This example guides you about attaching the second network interface to a pod with IP address assigned in the range you specified using whereabouts.
1. Install TCE Multus CNI package to support multiple network by following
[doc](https://github.com/vmware-tanzu/community-edition/blob/main/addons/packages/multus-cni/3.7.1/README.md#usage-example):
1. Install TCE whereabouts package through Tanzu CLI
```bash
tanzu package install whereabouts --package-name whereabouts.community.tanzu.vmware.com --version ${WHEREABOUTS_PACKAGE_VERSION}
```
> You can get the `${WHEREABOUTS_PACKAGE_VERSION}` from running `tanzu package
> available list whereabouts.community.tanzu.vmware.com`. Specifying a
> namespace may be required depending on where your package repository was
> installed.
1. After the Multus CNI and whereabouts DaemonSet are running, you can define your NetworkAttachmentDefinition to tell
* which CNI plugin will be used for the second network interface, in particular this example uses `ipvlan` CNI plugin
* what IP addressed will be assigned for the second network interface, in particular this example uses `whereabouts` CNI IPAM plugin
```bash
cat <<EOF | kubectl create -f -
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: ipvlan-conf-1
spec:
config: '{
"cniVersion": "0.3.0",
"name": "ipvlan-conf-1",
"type": "ipvlan",
"master": "eth0",
"mode": "bridge",
"ipam": {
"type": "whereabouts",
"range": "192.168.20.0/24",
"gateway": "192.168.20.1",
"range_start": "192.168.20.2",
"range_end": "192.168.20.100"
}
}'
EOF
```
1. Deploy a pod using the NetworkAttachmentDefinition named `ipvlan-conf-1` as above by adding following lines to the pod `metadata.annotations`:
```bash
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: ipvlan-conf-1
```
1. After the pod is running, run following command to describe your pod and there will be an event for adding the second network interface within IP range
we specified with whereabouts.
```bash
kubectl describe {your-pod}
... ...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedInterface 2m1s multus Add eth0 [100.96.1.6/24]
Normal AddedInterface 2m1s multus Add net1 [192.168.20.10/24] from default/ipvlan-conf-1
```
You can also run following command to check more details about the second network interface:
```bash
kubectl exec {your-pod} -- ip a
```
apiVersion: imgpkg.carvel.dev/v1alpha1
kind: Bundle
metadata:
name: whereabouts
authors:
- name: Jun Wang
email: wjun@vmware.com
- name: Chenrui Li
email: lchenrui@vmware.com
websites:
- url: github.com/vmware-tanzu/tce
- url: github.com/k8snetworkplumbingwg/whereabouts
---
apiVersion: imgpkg.carvel.dev/v1alpha1
images:
- annotations:
kbld.carvel.dev/id: ghcr.io/k8snetworkplumbingwg/whereabouts:latest-amd64
image: projects.registry.vmware.com/tce/whereabouts@sha256:362ff5654b1f67c3a7710a8d556224e90ee1012748703db5c09a0c48f84309c3
kind: ImagesLock
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.subset({"kind":"ServiceAccount"})
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: whereabouts
namespace: #@ data.values.namespace
#@overlay/match by=overlay.subset({"kind":"ClusterRoleBinding"})
---
apiVersion: rbac.authorization.k8s.io/v1
subjects:
#@overlay/match by=overlay.subset({"name": "whereabouts"})
- kind: ServiceAccount
name: whereabouts
namespace: #@ data.values.namespace
#@overlay/match by=overlay.subset({"kind": "DaemonSet", "metadata": {"name": "whereabouts"}})
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: whereabouts
namespace: #@ data.values.namespace
spec:
template:
spec:
#@overlay/replace via=lambda left, right: {"kubernetes.io/arch": left["beta.kubernetes.io/arch"]}
nodeSelector:
containers:
#@overlay/match by=overlay.subset({"name": "whereabouts"})
- name: whereabouts
resources:
limits:
cpu: #@ data.values.whereabouts.config.resources.limits.cpu
memory: #@ data.values.whereabouts.config.resources.limits.memory
requests:
cpu: #@ data.values.whereabouts.config.resources.requests.cpu
memory: #@ data.values.whereabouts.config.resources.requests.memory
#@ load("@ytt:data", "data")
#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.subset({"kind": "CronJob", "metadata": {"name": "ip-reconciler"}})
---
apiVersion: batch/v1
metadata:
name: ip-reconciler
namespace: #@ data.values.namespace
spec:
schedule: #@ data.values.ip_reconciler.config.schedule
jobTemplate:
spec:
template:
spec:
containers:
#@overlay/match by="name"
- name: whereabouts
resources:
requests:
cpu: #@ data.values.ip_reconciler.config.resources.requests.cpu
memory: #@ data.values.ip_reconciler.config.resources.requests.memory
apiVersion: v1
kind: ServiceAccount
metadata:
name: whereabouts
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: whereabouts
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: whereabouts-cni
subjects:
- kind: ServiceAccount
name: whereabouts
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: whereabouts-cni
rules:
- apiGroups:
- whereabouts.cni.cncf.io
resources:
- ippools
- overlappingrangeipreservations
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- '*'
- apiGroups: [""]
resources:
- pods
verbs:
- list
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: whereabouts
namespace: kube-system
labels:
tier: node
app: whereabouts
spec:
selector:
matchLabels:
name: whereabouts
updateStrategy:
type: RollingUpdate
template:
metadata:
labels:
tier: node
app: whereabouts
name: whereabouts
spec:
hostNetwork: true
serviceAccountName: whereabouts
nodeSelector:
beta.kubernetes.io/arch: amd64
tolerations:
- operator: Exists
effect: NoSchedule
containers:
- name: whereabouts
image: ghcr.io/k8snetworkplumbingwg/whereabouts:latest-amd64
env:
- name: WHEREABOUTS_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: true
volumeMounts:
- name: cnibin
mountPath: /host/opt/cni/bin
- name: cni-net-dir
mountPath: /host/etc/cni/net.d
volumes:
- name: cnibin
hostPath:
path: /opt/cni/bin
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: ip-reconciler
namespace: kube-system
labels:
tier: node
app: whereabouts
spec:
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 0
schedule: "*/5 * * * *"
jobTemplate:
spec:
backoffLimit: 0
template:
metadata:
labels:
app: whereabouts
spec:
priorityClassName: "system-node-critical"
serviceAccountName: whereabouts
containers:
- name: whereabouts
image: ghcr.io/k8snetworkplumbingwg/whereabouts:latest-amd64
resources:
requests:
cpu: "100m"
memory: "50Mi"
command:
- /ip-reconciler
- -log-level=verbose
volumeMounts:
- name: cni-net-dir
mountPath: /host/etc/cni/net.d
volumes:
- name: cni-net-dir
hostPath:
path: /etc/cni/net.d
restartPolicy: OnFailure
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
creationTimestamp: null
name: ippools.whereabouts.cni.cncf.io
spec:
group: whereabouts.cni.cncf.io
names:
kind: IPPool
listKind: IPPoolList
plural: ippools
singular: ippool
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: IPPool is the Schema for the ippools API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: IPPoolSpec defines the desired state of IPPool
properties:
allocations:
additionalProperties:
description: IPAllocation represents metadata about the pod/container
owner of a specific IP
properties:
id:
type: string
podref:
type: string
required:
- id
type: object
description: Allocations is the set of allocated IPs for the given
range. Its` indices are a direct mapping to the IP with the same
index/offset for the pool's range.
type: object
range:
description: Range is a RFC 4632/4291-style string that represents
an IP address and prefix length in CIDR notation
type: string
required:
- allocations
- range
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.4.1
creationTimestamp: null
name: overlappingrangeipreservations.whereabouts.cni.cncf.io
spec:
group: whereabouts.cni.cncf.io
names:
kind: OverlappingRangeIPReservation
listKind: OverlappingRangeIPReservationList
plural: overlappingrangeipreservations
singular: overlappingrangeipreservation
scope: Namespaced
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: OverlappingRangeIPReservation is the Schema for the OverlappingRangeIPReservations
API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: OverlappingRangeIPReservationSpec defines the desired state
of OverlappingRangeIPReservation
properties:
containerid:
type: string
podref:
type: string
required:
- containerid
type: object
required:
- spec
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
#@data/values
---
#! The namespace in which to deploy whereabouts components.
namespace: kube-system
whereabouts:
config:
resources:
limits:
cpu: 100m
memory: 50Mi
requests:
cpu: 100m
memory: 50Mi
ip_reconciler:
config:
schedule: "*/5 * * * *"
resources:
requests:
cpu: 100m
memory: 50Mi
apiVersion: vendir.k14s.io/v1alpha1
directories:
- contents:
- git:
commitTitle: Safer reconciler spec (#167)...
sha: abd29e856f368869b792668d5baa63b9d935032d
tags:
- v0.5.1
path: .
path: config/upstream
kind: LockConfig
apiVersion: vendir.k14s.io/v1alpha1
kind: Config
minimumRequiredVersion: 0.12.0
directories:
- path: "config/upstream"
contents:
- path: .
git:
url: https://github.com/k8snetworkplumbingwg/whereabouts
ref: v0.5.1
includePaths:
- doc/crds/*
newRootPath: doc/crds
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
name: whereabouts.community.tanzu.vmware.com.0.5.1
spec:
refName: whereabouts.community.tanzu.vmware.com
version: 0.5.1
releaseNotes: "whereabouts 0.5.1 https://github.com/k8snetworkplumbingwg/whereabouts/releases/tag/v0.5.1"
valuesSchema:
openAPIv3:
title: whereabouts.community.tanzu.vmware.com.0.5.1 values schema
properties:
namespace:
type: string
description: Namespace where whereabouts daemonset and ip-reconciler cronjob will be deployed.
default: kube-system
whereabouts:
type: object
description: Whereabouts Daemonset configuration.
properties:
config:
type: object
description: Daemonset config.
properties:
resources:
type: object
description: Daemonset resource related config.
properties:
limits:
type: object
description: Daemonset resource limits.
properties:
cpu:
type: string
description: Daemonset cpu limits.
default: 100m
memory:
type: string
description: Daemonset memory limits.
default: 50Mi
request:
type: object
description: Daemonset resource request.
properties:
cpu:
type: string
description: Daemonset cpu request.
default: 100m
memory:
type: string
description: Daemonset memory request.
default: 50Mi
ip_reconciler:
type: object
description: ip-reconciler CronJob configuration.
properties:
config:
type: object
description: Daemonset config.
properties:
schedule:
type: string
description: CronJob schedule.
default: "*/5 * * * *"
resources:
type: object
description: CronJob resource related config.
properties:
request:
type: object
description: CronJob resource request.
properties:
cpu:
type: string
description: CronJob cpu request.
default: 100m
memory:
type: string
description: CronJob memory request.
default: 50Mi
licenses:
- "Apache 2.0"
template:
spec:
fetch:
- imgpkgBundle:
image: projects.registry.vmware.com/tce/whereabouts@sha256:f0cefa94d98ce08c0cad598902b5dba75741ebf1ca17e3677395ce5ad7af3738
template:
- ytt:
paths:
- config/
- kbld:
paths:
- "-"
- .imgpkg/images.yml
deploy:
- kapp: {}
# Copyright 2021 VMware Tanzu Community Edition contributors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
ROOT_DIR := $(shell git rev-parse --show-toplevel)
VERSION ?= 0.5.1
USE_CONF_FILE ?= true
WHEREABOUTS_E2E_TEST_ROOT := "${ROOT_DIR}"/addons/packages/whereabouts/"${VERSION}"/test/e2e
.DEFAULT_GOAL := help
.PHONY: help
help: ## print help messages
@awk 'BEGIN {FS = ":.*##"; printf "Useful Targets:\n"} /^[a-z]+/ { printf " \033[0;34m%-8s\033[0m %s\n", $$1, $$2} ' ${MAKEFILE_LIST}
# tests for whereabouts
.PHONY: test
test: ## unit tests
@echo "TODO: No unit tests for ${VERSION} now"
e2e-test: ## e2e tests
@printf "\ne2e tests for whereabouts.${VERSION}\n\n"; \
cd "${WHEREABOUTS_E2E_TEST_ROOT}" && ginkgo --flakeAttempts=2 -v . -- --version=${VERSION} --whereabouts-use-conf=${USE_CONF_FILE}
lint: ## lint check for tests files
ifeq ($(origin GOLANGCI_LINT),undefined)
@echo "Error! GOLANGCI_LINT env var not set"
else
$(GOLANGCI_LINT) run -v --timeout=5m
endif
get-deps: ## get go sources dependencies.
go mod download
build: ## build
@echo "TODO: No build steps"
# WHEREABOUTS E2E TESTS
## Prerequisites
* A Tanzu Community Edition cluster and the cluster needs to be the
current-context. See the [Getting Started
Guide](https://tanzucommunityedition.io/docs/getting-started/) for
instuctions on how to create a cluster.
* The packages `multus-cni.community.tanzu.vmware.com` with version `3.7.1`
and `whereabouts.community.tanzu.vmware.com` with version `0.5.1` must
exist on the cluster so they can be installed by the test.
## USAGE
1. Run below command to run the e2e tests.
```bash
make e2e-test
```
apiVersion: v1
kind: Pod
metadata:
name: multi-nic-pod1
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-config
spec:
containers:
- name: multi-nic-pod
image: quay.io/centos/centos:8
command: ["/bin/sleep", "10000"]
securityContext:
privileged: true
---
apiVersion: "k8s.cni.cncf.io/v1"
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-config
spec:
config: '{
"cniVersion": "0.3.1",
"plugins": [
{
"type": "macvlan",
"capabilities": { "ips": true },
"master": "eth0",
"mode": "bridge",
"ipam": {
"type": "whereabouts",
"range": "192.168.20.0/24",
"range_start": "192.168.20.10",
"range_end": "192.168.20.100",
"gateway": "192.168.20.1"
}
}, {
"type": "tuning"
} ]
}'
---
apiVersion: v1
kind: Pod
metadata:
name: multi-nic-pod
annotations:
k8s.v1.cni.cncf.io/networks: macvlan-config
spec:
containers:
- name: multi-nic-pod
image: quay.io/centos/centos:8
command: ["/bin/sleep", "10000"]
securityContext:
privileged: true
namespace: kube-system
whereabouts:
config:
resources:
limits:
cpu: 100m
memory: 100Mi
requests:
cpu: 100m
memory: 100Mi
// Copyright 2021 VMware Tanzu Community Edition contributors. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package e2e_test
import (
"flag"
"strings"
"testing"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/vmware-tanzu/community-edition/addons/packages/test/pkg/utils"
)
type addonPackage struct {
name string
version string
fullVersion string
installedNamespace string
installedName string
}
var (
multusCNIPackage addonPackage
whereaboutsPackage addonPackage
multusCNIUseConfFile bool
whereaboutsUseConfFile bool
packageVersion string
)
func init() {
flag.BoolVar(&multusCNIUseConfFile, "multuscni-use-conf", true, "use configuration file or not")
flag.BoolVar(&whereaboutsUseConfFile, "whereabouts-use-conf", true, "use configuration file or not")
flag.StringVar(&packageVersion, "version", "0.5.1", "the version of the package to test")
}
func TestWhereaboutsE2E(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Whereabouts addon E2E Test Suite")
}
var _ = BeforeSuite(func() {
// As Whereabouts CNI plugin usually works with a meta CNI plugin like multus-cni, we need to install multus-cni package as well.
// Needs to have package related values predefined.
multusCNIpackageName := utils.TanzuPackageName("multus-cni")
multusCNIPackage = addonPackage{
name: multusCNIpackageName,
version: "3.7.1",
fullVersion: utils.TanzuPackageAvailableVersionWithVersionSubString(multusCNIpackageName, "3.7.1"),
installedNamespace: "default",
installedName: "multus-cni-pkg",
}
whereaboutsPackageName := utils.TanzuPackageName("whereabouts")
whereaboutsPackage = addonPackage{
name: whereaboutsPackageName,
version: "0.5.1",
fullVersion: utils.TanzuPackageAvailableVersionWithVersionSubString(whereaboutsPackageName, "0.5.1"),
installedNamespace: "default",
installedName: "whereabouts-pkg",
}
if strings.Compare(multusCNIPackage.installedNamespace, "default") != 0 {
_, err := utils.Kubectl(nil, "create", "ns", multusCNIPackage.installedNamespace)
Expect(err).NotTo(HaveOccurred())
}
if strings.Compare(whereaboutsPackage.installedNamespace, "default") != 0 {
_, err := utils.Kubectl(nil, "create", "ns", whereaboutsPackage.installedNamespace)
Expect(err).NotTo(HaveOccurred())
}
})
var _ = AfterSuite(func() {
if strings.Compare(multusCNIPackage.installedNamespace, "default") != 0 {
_, err := utils.Kubectl(nil, "delete", "ns", multusCNIPackage.installedNamespace)
Expect(err).NotTo(HaveOccurred())
}
if strings.Compare(whereaboutsPackage.installedNamespace, "default") != 0 {
_, err := utils.Kubectl(nil, "delete", "ns", whereaboutsPackage.installedNamespace)
Expect(err).NotTo(HaveOccurred())
}
})
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment