Skip to content

Commit

Permalink
Refactor...
Browse files Browse the repository at this point in the history
- Split the Dockerfile into a release build and a test
  image build
- Implement a test registry to support the split build
- Fully support non-default namespace
  • Loading branch information
amigus committed Feb 14, 2020
1 parent de37a66 commit 1b15461
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 72 deletions.
28 changes: 0 additions & 28 deletions Dockerfile

This file was deleted.

98 changes: 62 additions & 36 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,63 +1,89 @@
NAME:=dsv-injector
VERSION?=latest

NAME=dsv-injector
VERSION?=0.0.1
IMAGE_TAG=$(NAME):$(VERSION)

# The Kubernetes cluster Namespace in which to deploy the Webhook and/or POD
NAMESPACE?=default
image:
docker build . -t $(IMAGE_TAG) -f build/Dockerfile

# The JSON file containing a mapping of DSV role names to tenant/credential pairs
ROLES_FILE?=configs/roles.json
### The recipes below build and deploy a test injector-svc 🥼🧪

# The TCP port on which the service should listen
SERVICE_PORT?=8543
# The CA certificate of the Kubernetes cluster 🔐
CA_CRT?=${HOME}/.minikube/ca.crt

CA_CRT=${HOME}/.minikube/ca.crt

# The IP address of the host of the dsv-injector service
HOST_IP?=$(shell ip -o -4 -br addr show dev eth0 | awk '{print $$3}' | sed -e 's|/.*$$||')
# The TCP port on which the service should listen 🌐
SERVICE_PORT?=8543

BUILD_DIR?=.build
IMAGE_TAG?=$(NAME):v$(VERSION)
# The Kubernetes cluster Namespace in which to deploy the Webhook and/or POD
NAMESPACE?=default

all: image deploy_host
# The JSON file containing a mapping of DSV role names to tenant/credentials 🔑
ROLES_FILE?=configs/roles.json

build:
mkdir -p $(BUILD_DIR)
# The IP address of the host running the dsv-injector service 🖥️
HOST_IP?=$(shell ip -o -4 -br addr | sed -n 2p | awk '{print $$3}' | sed -e 's|/.*$$||')

clean:
rm -rf $(BUILD_DIR)
kubectl delete --ignore-not-found deployments $(NAME)
kubectl delete --ignore-not-found service $(NAME)
kubectl delete --ignore-not-found mutatingwebhookconfigurations.admissionregistration.k8s.io $(NAME)
TEST_IMAGE_TAG?=$(NAME)-test:$(VERSION)

cert=$(BUILD_DIR)/$(NAME).pem
BUILD_DIR=target

$(cert): build
sh scripts/get_cert.sh -n "$(NAME)" -N "$(NAMESPACE)" -d "$(BUILD_DIR)"
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

ca_bundle=$(shell base64 -w0 $(CA_CRT))

deploy_webhook: $(cert) image
sed -e "s| port: [0-9]*.*$$| port: $(SERVICE_PORT)|" \
deploy_webhook: $(BUILD_DIR)
sed -e "s| namespace: .*$$| namespace: $(NAMESPACE)|" \
-e "s| port: [0-9]*.*$$| port: $(SERVICE_PORT)|" \
-e "s|caBundle:.*$$|caBundle: $(ca_bundle)|" \
deployments/webhook.yml >| $(BUILD_DIR)/webhook.yml
kubectl apply -f $(BUILD_DIR)/webhook.yml

deploy_host: deploy_webhook
sed -e "s|- port: [0-9]*.*$$|- port: $(SERVICE_PORT)|" \
sed -e "s| namespace: .*$$| namespace: $(NAMESPACE)|" \
-e "s|- port: [0-9]*.*$$|- port: $(SERVICE_PORT)|" \
-e "s|- ip: *\"[0-9].*$$|- ip: \"$(HOST_IP)\"|" \
deployments/host.yml >| $(BUILD_DIR)/host.yml
kubectl apply -f $(BUILD_DIR)/host.yml

deploy_pod: deploy_webhook
sed -e "s|- port: [0-9]*.*$$|- port: $(SERVICE_PORT)|" \
-e "s|image:.*$$|image: $(IMAGE_TAG)|" \
deployments/pod.yml >| $(BUILD_DIR)/pod.yml
kubectl apply -f $(BUILD_DIR)/pod.yml
# Create a test image that includes the certficate and roles.json 🔓😧

image: $(cert)
docker build -t $(IMAGE_TAG) . \
$(BUILD_DIR)/$(NAME).key $(BUILD_DIR)/$(NAME).pem: $(BUILD_DIR)
sh scripts/get_cert.sh -n "$(NAME)" -N "$(NAMESPACE)" -d "$(BUILD_DIR)"

# The registry can be supplied; spin up a test registry when it is not 🏗️
registry:
ifndef REGISTRY
kubectl apply -f test/registry.yml
@echo "Waiting for the test registry to spin up..." && sleep 6
REGISTRY=$(shell kubectl get service -n kube-system kube-registry -o json |\
jq -r ".spec.clusterIP,.spec.ports[0].port" | sed -e "N;s|\n|:|")
endif

$(BUILD_DIR)/Dockerfile: registry test/Dockerfile $(BUILD_DIR)
sed -e "s|^FROM $(NAME):.*|FROM $(REGISTRY)/$(IMAGE_TAG)|" \
test/Dockerfile >| $(BUILD_DIR)/Dockerfile

test_image: image $(BUILD_DIR)/$(NAME).key $(BUILD_DIR)/$(NAME).pem $(BUILD_DIR)/Dockerfile
docker tag $(IMAGE_TAG) $(REGISTRY)/$(IMAGE_TAG)
docker push $(REGISTRY)/$(IMAGE_TAG)
docker build . -t $(TEST_IMAGE_TAG) -f $(BUILD_DIR)/Dockerfile \
--build-arg cert_file="$(BUILD_DIR)/$(NAME).pem" \
--build-arg key_file="$(BUILD_DIR)/$(NAME).key" \
--build-arg roles_file="$(ROLES_FILE)" \
--build-arg roles_file="$(ROLES_FILE)"

deploy: deploy_webhook test_image
sed -e "s| namespace: .*$$| namespace: $(NAMESPACE)|" \
-e "s|- port: [0-9]*.*$$|- port: $(SERVICE_PORT)|" \
-e "s|image:.*$$|image: $(TEST_IMAGE_TAG)|" \
deployments/pod.yml >| $(BUILD_DIR)/pod.yml
kubectl apply -f $(BUILD_DIR)/pod.yml

deploy_clean:
docker rmi -f $(IMAGE_TAG)
kubectl delete --ignore-not-found deployments $(NAME)
kubectl delete --ignore-not-found service $(NAME)
kubectl delete --ignore-not-found mutatingwebhookconfigurations.admissionregistration.k8s.io $(NAME)

clean: deploy_clean
rm -rf $(BUILD_DIR) $(NAME)
34 changes: 26 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@ specify a particular Role.

## Build

The build requires a functional Minikube installation. It uses a the `Makefile`.
Building the `dsv-injector` image requires docker

Building and deploying the test_image requires a Kubernetes cluster.

The `Makefile` defaults were set based on Minikube.

To build the [Docker](https://www.docker.com/) image run:

```sh
make image
```

## Test

To configure the Kubernetes cluster to to call the webhook as stand-alone
service running on the host at `$(HOST_IP)`:

Expand All @@ -61,21 +67,33 @@ make deploy_host
```

Note that `$(HOST_IP)` defaults to the IP address of the host executing the
build. Also note that the `Makefile` does not include`docker login` or
`docker push` as neither are required to deploy the webhook to Minikube.
build.

To deploy the `dsv-injector` service as a POD and configure the webhook to call
it, run:

```sh
make deploy
```

Note that, unless an existing `$(REGISTRY)` is specified, the build will start
one on the cluster so it can make the release image available to the test image.

Also note that the `Makefile` does not include `docker login`.

## The CA Certificate

The `Makefile` requires access to the Kubernetes CA certificate. It assumes that
it is available in `${HOME}/.minikube/ca.crt` but that can be overridden by
setting `$(CA_CRT)`.
The WebHook uses the cluster CA certificate. The default location is
`${HOME}/.minikube/ca.crt` but that can be overridden by setting `$(CA_CRT)`.

The location of the CA certificate can be gotten from the cluster configuration:

```shell
kubectl config view --raw -o json | jq -r '.clusters[0].cluster."certificate-authority"'
```

If the above returns `null` then the certificate is embedded in the cluster
configuration. In that case, set `$(ca_bundle)` to the output of:
If that returns `null` then the certificate is embedded in the cluster configuration.
In that case, set `$(ca_bundle)` to the output of:

```shell
kubectl config view --raw -o json | jq -r '.clusters[0].cluster."certificate-authority-data"' | tr -d '"'
Expand Down
18 changes: 18 additions & 0 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM alpine:latest AS build
RUN apk update && apk upgrade
RUN apk add go

WORKDIR /b
COPY cmd/ ./cmd
COPY pkg/ ./pkg
COPY go.mod go.sum ./
RUN go build cmd/injector-svc.go

FROM alpine:latest
RUN apk update && apk upgrade
RUN addgroup dsv && adduser -S -G dsv dsv

WORKDIR /home/dsv
COPY --chown=dsv:dsv --from=build /b/injector-svc .

USER dsv
2 changes: 2 additions & 0 deletions deployments/host.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ apiVersion: v1
kind: Service
metadata:
name: dsv-injector
namespace: default
spec:
type: ClusterIP
ports:
Expand All @@ -13,6 +14,7 @@ kind: Endpoints
apiVersion: v1
metadata:
name: dsv-injector
namespace: default
subsets:
- addresses:
- ip: "192.168.1.1"
Expand Down
3 changes: 3 additions & 0 deletions deployments/pod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: dsv-injector
namespace: default
labels:
app: dsv-injector
spec:
Expand All @@ -14,6 +15,7 @@ spec:
metadata:
labels:
app: dsv-injector
namespace: default
spec:
containers:
- name: dsv-injector
Expand All @@ -33,6 +35,7 @@ apiVersion: v1
kind: Service
metadata:
name: dsv-injector
namespace: default
labels:
app: dsv-injector
spec:
Expand Down
13 changes: 13 additions & 0 deletions test/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM dsv-injector:latest

ARG cert_file
ARG key_file
ARG roles_file

WORKDIR /home/dsv

COPY --chown=dsv:dsv ${cert_file} ./dsv.pem
COPY --chown=dsv:dsv ${key_file} ./dsv.key
COPY --chown=dsv:dsv ${roles_file} ./roles.json

ENTRYPOINT ["./injector-svc", "-cert", "dsv.pem", "-key", "dsv.key", "-roles", "roles.json" ]
62 changes: 62 additions & 0 deletions test/registry.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
apiVersion: v1
kind: ReplicationController
metadata:
name: kube-registry-v0
namespace: kube-system
labels:
k8s-app: kube-registry
version: v0
spec:
replicas: 1
selector:
k8s-app: kube-registry
version: v0
template:
metadata:
labels:
k8s-app: kube-registry
version: v0
spec:
containers:
- name: registry
image: registry:2.5.1
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2048Mi"
cpu: "1000m"
env:
- name: REGISTRY_HTTP_ADDR
value: :5000
- name: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
value: /var/lib/registry
volumeMounts:
- name: image-store
mountPath: /var/lib/registry
ports:
- containerPort: 5000
name: registry
protocol: TCP
volumes:
- name: image-store
hostPath:
path: /data/registry/
---
apiVersion: v1
kind: Service
metadata:
name: kube-registry
namespace: kube-system
labels:
k8s-app: kube-registry
spec:
type: ClusterIP
selector:
k8s-app: kube-registry
ports:
- name: registry
port: 5000
protocol: TCP

0 comments on commit 1b15461

Please sign in to comment.