Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move to scratch docker image #2705

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ mocks:
GO111MODULE=on go generate ./...

tools:
GO111MODULE=on go get -d k8s.io/client-go@kubernetes-1.28.10
GO111MODULE=on go get -d k8s.io/client-go@kubernetes-1.29.2
GO111MODULE=on go install github.com/golang/mock/[email protected]
GO111MODULE=on go mod tidy

Expand Down
6 changes: 4 additions & 2 deletions docker/DebugDockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
FROM golang:1.22-alpine
FROM golang:1.22
LABEL maintainer="Team ACID @ Zalando <[email protected]>"

ENV DEBIAN_FRONTEND=noninteractive

# We need root certificates to deal with teams api over https
RUN apk -U add --no-cache ca-certificates delve
RUN apt update && apt install -y ca-certificates delve

COPY build/* /

Expand Down
22 changes: 11 additions & 11 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
ARG BASE_IMAGE=registry.opensource.zalan.do/library/alpine-3:latest
FROM golang:1.22-alpine AS builder
FROM golang:1.22 AS builder
ARG VERSION=latest

ENV DEBIAN_FRONTEND=noninteractive

# We need root certificates to deal with teams api over https
RUN apt update && apt install -y ca-certificates

COPY . /go/src/github.com/zalando/postgres-operator
WORKDIR /go/src/github.com/zalando/postgres-operator

RUN GO111MODULE=on go mod vendor \
&& CGO_ENABLED=0 go build -o build/postgres-operator -v -ldflags "-X=main.version=${VERSION}" cmd/main.go
&& CGO_ENABLED=0 go build -o build/postgres-operator -v -ldflags "-s -w -X=main.version=${VERSION}" cmd/main.go

FROM ${BASE_IMAGE}
FROM scratch
LABEL maintainer="Team ACID @ Zalando <[email protected]>"
LABEL org.opencontainers.image.source="https://github.com/zalando/postgres-operator"

# We need root certificates to deal with teams api over https
RUN apk -U upgrade --no-cache \
&& apk add --no-cache curl ca-certificates

COPY --from=builder /go/src/github.com/zalando/postgres-operator/build/* /
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt

RUN addgroup -g 1000 pgo
RUN adduser -D -u 1000 -G pgo -g 'Postgres Operator' pgo

# since the ID instead of the name, no passwd file is needed
# if using name (like pgo), then there must be an entry to map to an ID.
USER 1000:1000

ENTRYPOINT ["/postgres-operator"]
30 changes: 0 additions & 30 deletions docker/build_operator.sh

This file was deleted.

4 changes: 2 additions & 2 deletions e2e/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# An image to run e2e tests.
# The image does not include the tests; all necessary files are bind-mounted when a container starts.
FROM ubuntu:20.04
FROM ubuntu:22.04
LABEL maintainer="Team ACID @ Zalando <[email protected]>"

ENV TERM xterm-256color
Expand All @@ -15,7 +15,7 @@ RUN apt-get update \
curl \
vim \
&& pip3 install --no-cache-dir -r requirements.txt \
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.24.3/bin/linux/amd64/kubectl \
&& curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.29.2/bin/linux/amd64/kubectl \
&& chmod +x ./kubectl \
&& mv ./kubectl /usr/local/bin/kubectl \
&& apt-get clean \
Expand Down
4 changes: 3 additions & 1 deletion e2e/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
kubernetes==29.2.0
kubernetes==30.1.0
timeout_decorator==0.5.0
pyyaml==6.0.1
kr8s==0.17.0
requests==2.32.3
15 changes: 13 additions & 2 deletions e2e/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@ IFS=$'\n\t'
readonly cluster_name="postgres-operator-e2e-tests"
readonly kubeconfig_path="/tmp/kind-config-${cluster_name}"
readonly spilo_image="registry.opensource.zalan.do/acid/spilo-16-e2e:0.1"
readonly e2e_test_runner_image="registry.opensource.zalan.do/acid/postgres-operator-e2e-tests-runner:0.4"
readonly e2e_test_runner_image="registry.opensource.zalan.do/acid/postgres-operator-e2e-tests-runner:0.5"

export GOPATH=${GOPATH-~/go}
export PATH=${GOPATH}/bin:$PATH

echo "Clustername: ${cluster_name}"
echo "Kubeconfig path: ${kubeconfig_path}"

# build the e2e image if it doesn't exist
function pull_or_build_e2e(){
if ! docker manifest inspect "${e2e_test_runner_image}" >/dev/null 2>&1; then
IMAGE=${e2e_test_runner_image%:*} TAG=${e2e_test_runner_image#*:} make docker
fi
}

function pull_images(){
operator_tag=$(git describe --tags --always --dirty)
if [[ -z $(docker images -q registry.opensource.zalan.do/acid/postgres-operator:${operator_tag}) ]]
Expand Down Expand Up @@ -47,12 +54,15 @@ function load_operator_image() {
}

function set_kind_api_server_ip(){
local tmpfile=$(mktemp)
echo "Setting up kind API server ip"
# use the actual kubeconfig to connect to the 'kind' API server
# but update the IP address of the API server to the one from the Docker 'bridge' network
readonly local kind_api_server_port=6443 # well-known in the 'kind' codebase
readonly local kind_api_server=$(docker inspect --format "{{ .NetworkSettings.Networks.kind.IPAddress }}:${kind_api_server_port}" "${cluster_name}"-control-plane)
sed -i "s/server.*$/server: https:\/\/$kind_api_server/g" "${kubeconfig_path}"
# support older sed versions (darwin)
sed "s/server.*$/server: https:\/\/$kind_api_server/g" "${kubeconfig_path}" > "${tmpfile}"
mv "${tmpfile}" "${kubeconfig_path}"
}

function generate_certificate(){
Expand Down Expand Up @@ -84,6 +94,7 @@ function main(){
echo "Entering main function..."
[[ -z ${NOCLEANUP-} ]] && trap "cleanup" QUIT TERM EXIT
pull_images
pull_or_build_e2e
[[ ! -f ${kubeconfig_path} ]] && start_kind
load_operator_image
set_kind_api_server_ip
Expand Down
58 changes: 38 additions & 20 deletions e2e/tests/k8s_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
import time
import subprocess
import warnings
import socket
import requests
from kr8s.objects import Pod

from kubernetes import client, config
from kubernetes.client.rest import ApiException
Expand All @@ -10,7 +13,6 @@
def to_selector(labels):
return ",".join(["=".join(lbl) for lbl in labels.items()])


class K8sApi:

def __init__(self):
Expand Down Expand Up @@ -285,15 +287,25 @@ def create_with_kubectl(self, path):

def exec_with_kubectl(self, pod, cmd):
return subprocess.run(["./exec.sh", pod, cmd],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

def portforward_req(self, pod, port, path):
pod = Pod.get(pod)
with pod.portforward(remote_port=port) as local_port:
# Make an API request
try:
resp = requests.get(f"http://localhost:{local_port}{path}")
if resp.status_code == 200:
return resp.json()
else:
return {"fail"}
except:
# ignore connection closed from requests
pass

def patroni_rest(self, pod, path):
r = self.exec_with_kubectl(pod, "curl localhost:8008/" + path)
if not r.returncode == 0 or not r.stdout.decode()[0:1] == "{":
return None

return json.loads(r.stdout.decode())
return self.portforward_req(pod, "8008", path)

def get_patroni_state(self, pod):
r = self.exec_with_kubectl(pod, "patronictl list -f json")
Expand All @@ -307,11 +319,7 @@ def get_operator_state(self):
return None
pod = pod.metadata.name

r = self.exec_with_kubectl(pod, "curl localhost:8080/workers/all/status/")
if not r.returncode == 0 or not r.stdout.decode()[0:1] == "{":
return None

return json.loads(r.stdout.decode())
return self.portforward_req(pod, "8080", "/workers/all/status/")

def get_patroni_running_members(self, pod="acid-minimal-cluster-0"):
result = self.get_patroni_state(pod)
Expand Down Expand Up @@ -566,15 +574,25 @@ def create_with_kubectl(self, path):

def exec_with_kubectl(self, pod, cmd):
return subprocess.run(["./exec.sh", pod, cmd],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)

def patroni_rest(self, pod, path):
r = self.exec_with_kubectl(pod, "curl localhost:8008/" + path)
if not r.returncode == 0 or not r.stdout.decode()[0:1] == "{":
return None
def portforward_req(self, pod, port, path):
pod = Pod.get(pod)
with pod.portforward(remote_port=port) as local_port:
# Make an API request
try:
resp = requests.get(f"http://localhost:{local_port}{path}")
if resp.status_code == 200:
return resp.json()
else:
return {"fail"}
except:
# ignore connection closed from requests
pass

return json.loads(r.stdout.decode())
def patroni_rest(self, pod, path):
return self.portforward_req(pod, "8008", path)

def get_patroni_state(self, pod):
r = self.exec_with_kubectl(pod, "patronictl list -f json")
Expand Down
14 changes: 6 additions & 8 deletions e2e/tests/test_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ def test_config_update(self):
self.eventuallyEqual(lambda: k8s.get_operator_state(), {"0": "idle"}, "Operator does not get in sync")

def compare_config():
effective_config = k8s.patroni_rest(leader.metadata.name, "config")
effective_config = k8s.patroni_rest(leader.metadata.name, "/config")
desired_config = pg_patch_config["spec"]["patroni"]
desired_parameters = pg_patch_config["spec"]["postgresql"]["parameters"]
effective_parameters = effective_config["postgresql"]["parameters"]
Expand Down Expand Up @@ -979,16 +979,14 @@ def test_infrastructure_roles(self):
def verify_role():
try:
operator_pod = k8s.get_operator_pod()
get_config_cmd = "wget --quiet -O - localhost:8080/config"
result = k8s.exec_with_kubectl(operator_pod.metadata.name,
get_config_cmd)
config_path = "/config"
result = k8s.portforward_req(operator_pod.metadata.name,
"8080", config_path)
try:
roles_dict = (json.loads(result.stdout)
.get("controller", {})
.get("InfrastructureRoles"))
roles_dict = (result.get("controller", {})
.get("InfrastructureRoles"))
except:
return False

if "robot_zmon_acid_monitoring_new" in roles_dict:
role = roles_dict["robot_zmon_acid_monitoring_new"]
role.pop("Password", None)
Expand Down