Skip to content

Commit a3e8701

Browse files
committed
add emr CICD entrypoint script
Signed-off-by: Oleg Avdeev <oleg.v.avdeev@gmail.com>
1 parent 8d5518d commit a3e8701

2 files changed

Lines changed: 158 additions & 1 deletion

File tree

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
STEP_BREADCRUMB='~~~~~~~~'
6+
SECONDS=0
7+
TIMEFORMAT="${STEP_BREADCRUMB} took %R seconds"
8+
9+
function maybe_build_push_docker {
10+
# Build and push docker image, tagged with SHA tag, if it doesn't exist already.
11+
NAME=$1
12+
TARGET=$NAME-docker
13+
SUFFIX=feast-$NAME
14+
15+
if ! aws ecr describe-images --repository-name "feast-ci/feast/$SUFFIX" "--image-ids=imageTag=${GIT_TAG}" >/dev/null ; then
16+
make "build-$TARGET" "push-$TARGET" REGISTRY="${DOCKER_REPOSITORY}" VERSION="${GIT_TAG}"
17+
else
18+
echo "Image ${DOCKER_REPOSITORY}/$SUFFIX:$GIT_TAG already exists, skipping docker build"
19+
fi
20+
}
21+
22+
source infra/scripts/k8s-common-functions.sh
23+
24+
GIT_TAG=${CODEBUILD_RESOLVED_SOURCE_VERSION}
25+
26+
echo "########## Starting stage $STAGE for ${CODEBUILD_SOURCE_REPO_URL} ${GIT_TAG} ###########"
27+
28+
# This seems to make builds a bit faster.
29+
export DOCKER_BUILDKIT=1
30+
31+
# Workaround for COPY command in core docker image that pulls local maven repo into the image
32+
# itself.
33+
mkdir .m2 2>/dev/null || true
34+
mkdir deps/feast/.m2 2>/dev/null || true
35+
36+
# Log into k8s.
37+
echo "${STEP_BREADCRUMB} Updating kubeconfig"
38+
aws eks update-kubeconfig --name "$EKS_CLUSTER_NAME"
39+
40+
# chmod kubeconfig so it doesn't complain all the time
41+
chmod 755 ~/.kube/config
42+
43+
# Sanity check that kubectl is working.
44+
echo "${STEP_BREADCRUMB} k8s sanity check"
45+
kubectl get pods
46+
47+
case $STAGE in
48+
core-docker)
49+
maybe_build_push_docker core
50+
;;
51+
serving-docker)
52+
maybe_build_push_docker serving
53+
;;
54+
jupyter-docker)
55+
maybe_build_push_docker jupyter
56+
;;
57+
jobservice-docker)
58+
maybe_build_push_docker jobservice
59+
;;
60+
ci-docker)
61+
maybe_build_push_docker ci
62+
;;
63+
e2e-test-emr)
64+
# EMR test - runs in default namespace.
65+
66+
# Copy cluster config template generated for us by terraform.
67+
aws s3 cp "${EMR_TEMPLATE_YML}" emr_cluster.yaml
68+
69+
# Delete old helm release and PVCs
70+
k8s_cleanup cicd default
71+
72+
# Create cluster OR get existing EMR cluster id. In the latter case, clean up any steps
73+
# already running there from previous test runs.
74+
echo "${STEP_BREADCRUMB} Creating EMR cluster, this can take up 10 minutes."
75+
CLUSTER_ID=$(time emr_cluster.py --template emr_cluster.yaml ensure --cleanup)
76+
77+
# Get (any) node IP. EMR will use this to connect to Kafka and Redis. We make them
78+
# available to the EMR job by exposing them as NodePort services.
79+
NODE_IP=$(kubectl get nodes -o custom-columns=Name:.metadata.name | tail -n1)
80+
81+
# Helm install everything.
82+
#
83+
# This may occasionally run into "provided port is already allocated" error due to
84+
# https://github.com/kubernetes/kubernetes/issues/85894
85+
helm_install cicd "$DOCKER_REPOSITORY" "$GIT_TAG" default \
86+
--set "redis.master.service.type=NodePort" \
87+
--set "redis.master.service.nodePort=32379" \
88+
--set "kafka.externalAccess.service.type=NodePort" \
89+
--set "kafka.externalAccess.enabled=true" \
90+
--set "kafka.externalAccess.service.nodePorts[0]=30092" \
91+
--set "kafka.externalAccess.service.domain=${NODE_IP}" \
92+
--set "kafka.service.externalPort=30094"
93+
94+
# Run the test suite as a one-off pod. We could also run it here, in the codebuild container
95+
# itself, but that'd require more networking setup to make feast services available
96+
# outside k8s cluster.
97+
kubectl delete pod ci-test-runner 2>/dev/null || true
98+
99+
echo "${STEP_BREADCRUMB} Running the test suite"
100+
time kubectl run --rm -i ci-test-runner \
101+
--restart=Never \
102+
--image="${DOCKER_REPOSITORY}/feast-ci:${GIT_TAG}" \
103+
--env="CLUSTER_ID=$CLUSTER_ID" \
104+
--env="STAGING_PATH=$STAGING_PATH" \
105+
--env="NODE_IP=$NODE_IP" \
106+
-- \
107+
bash -c "mkdir src && cd src && git clone $CODEBUILD_SOURCE_REPO_URL && cd feast* && git config remote.origin.fetch '+refs/pull/*:refs/remotes/origin/pull/*' && git fetch -q && git checkout $CODEBUILD_RESOLVED_SOURCE_VERSION && ./infra/scripts/setup-e2e-env-aws.sh && ./infra/scripts/test-end-to-end-aws.sh"
108+
109+
;;
110+
e2e-test-sparkop)
111+
# spark k8s test - runs in sparkop namespace (so it doesn't interfere with a concurrently
112+
# running EMR test).
113+
NAMESPACE=sparkop
114+
RELEASE=sparkop
115+
116+
# Clean up old release
117+
k8s_cleanup "$RELEASE" "$NAMESPACE"
118+
119+
# Helm install everything in a namespace
120+
helm_install "$RELEASE" "${DOCKER_REPOSITORY}" "${GIT_TAG}" "$NAMESPACE"
121+
122+
# Delete old test running pod if it exists
123+
kubectl delete pod -n "$NAMESPACE" ci-test-runner 2>/dev/null || true
124+
125+
# Delete all sparkapplication resources that may be left over from the previous test runs.
126+
kubectl delete sparkapplication --all -n "$NAMESPACE" || true
127+
128+
# Make sure the test pod has permissions to create sparkapplication resources
129+
setup_sparkop_role
130+
131+
# Run the test suite as a one-off pod.
132+
echo "${STEP_BREADCRUMB} Running the test suite"
133+
if ! time kubectl run --rm -n "$NAMESPACE" -i ci-test-runner \
134+
--restart=Never \
135+
--image="${DOCKER_REPOSITORY}/feast-ci:${GIT_TAG}" \
136+
--env="STAGING_PATH=$STAGING_PATH" \
137+
-- \
138+
bash -c "mkdir src && cd src && git clone $CODEBUILD_SOURCE_REPO_URL && cd feast* && git config remote.origin.fetch '+refs/pull/*:refs/remotes/origin/pull/*' && git fetch -q && git checkout $CODEBUILD_RESOLVED_SOURCE_VERSION && ./infra/scripts/setup-e2e-env-sparkop.sh && ./infra/scripts/test-end-to-end-sparkop.sh" ; then
139+
140+
readarray -t CRASHED_PODS < <(kubectl get pods --no-headers=true --namespace sparkop | grep Error | awk '{ print $1 }')
141+
142+
for POD in "${CRASHED_PODS[@]}"; do
143+
echo "Logs from crashed pod $POD:"
144+
kubectl logs --namespace sparkop "$POD"
145+
done
146+
fi
147+
148+
;;
149+
cleanup)
150+
emr_cluster.py --template emr_cluster.yaml destroy
151+
;;
152+
*)
153+
echo "Unknown stage $STAGE"
154+
;;
155+
esac
156+
157+
echo "########## Stage $STAGE took $SECONDS seconds ###########"

infra/scripts/k8s-common-functions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function helm_install {
5656
# has some issues with unbound PVCs (that cause kubectl delete pvc to hang).
5757
echo "${STEP_BREADCRUMB:-} Helm installing feast"
5858

59-
if ! time helm install --wait "$RELEASE" ./infra/charts/feast \
59+
if ! time helm install --wait "$RELEASE" "${HELM_CHART_LOCATION:-./infra/charts/feast}" \
6060
--timeout 15m \
6161
--set "feast-jupyter.image.repository=${DOCKER_REPOSITORY}/feast-jupyter" \
6262
--set "feast-jupyter.image.tag=${GIT_TAG}" \

0 commit comments

Comments
 (0)