Skip to content

Commit d5f618c

Browse files
committed
K8s config and productionizing server
1 parent c26bd98 commit d5f618c

File tree

7 files changed

+363
-20
lines changed

7 files changed

+363
-20
lines changed

.github/workflows/build-server.yml

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# build.yml
2+
on:
3+
# pull_request:
4+
# paths:
5+
# - desci-server/**
6+
push:
7+
paths:
8+
- .github/workflows/**
9+
- desci-server/**
10+
- desci-contracts/**
11+
- Dockerfile
12+
branches: # array of glob patterns matching against refs/heads. Optional; defaults to all
13+
- main # triggers on pushes that contain changes
14+
- develop
15+
16+
name: Build automating-metadata
17+
18+
# https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html
19+
env:
20+
AWS_DEFAULT_REGION: us-east-2
21+
AWS_DEFAULT_OUTPUT: json
22+
AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
23+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
24+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
25+
CONTAINER_IMAGE: automating-metadata
26+
DOCKER_BUILDKIT: 1
27+
28+
jobs:
29+
build-and-push-images:
30+
# we build and push for every commit, even if tests pass, that way when tests pass deployment is short (run test + build in parallel)
31+
name: Build and push images
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: hashicorp/setup-terraform@v1
35+
- name: Checkout
36+
uses: actions/checkout@v4
37+
38+
# Add steps here like linting, testing, minification, etc.
39+
- id: install-aws-cli
40+
uses: unfor19/install-aws-cli-action@v1
41+
with:
42+
version: 1
43+
44+
- uses: prepor/action-aws-iam-authenticator@master
45+
- run: aws-iam-authenticator version
46+
47+
- name: Install Kubectl
48+
run: |
49+
#$(curl -Ls https://dl.k8s.io/release/stable.txt)
50+
version=v1.23.6
51+
echo "using kubectl@$version"
52+
curl -sLO "https://dl.k8s.io/release/$version/bin/linux/amd64/kubectl" -o kubectl
53+
chmod +x kubectl
54+
mv kubectl /usr/local/bin
55+
mkdir $HOME/.kube
56+
sudo apt-get update
57+
sudo apt-get install less
58+
echo ${{ secrets.KUBE_CONFIG_DATA }} | base64 --decode > $HOME/.kube/config
59+
aws sts get-caller-identity
60+
61+
- name: Build and tag the image (DEV)
62+
if: github.ref == 'refs/heads/develop'
63+
run: |
64+
# Build and tag the image
65+
docker build \
66+
-t $CONTAINER_IMAGE-dev:${{ github.sha }} \
67+
-t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev \
68+
.
69+
70+
- name: Build and tag the image (PROD)
71+
if: github.ref == 'refs/heads/main'
72+
run: |
73+
# Build and tag the image
74+
docker build \
75+
-t $CONTAINER_IMAGE-prod:${{ github.sha }} \
76+
-t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod \
77+
.
78+
79+
- name: Push (DEV)
80+
if: github.ref == 'refs/heads/develop'
81+
run: |
82+
# Push image to AWS ECR
83+
aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
84+
docker tag $CONTAINER_IMAGE-dev:${{ github.sha }} $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:${{ github.sha }}
85+
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:${{ github.sha }}
86+
87+
- name: Push (PROD)
88+
if: github.ref == 'refs/heads/main'
89+
run: |
90+
# Push image to AWS ECR
91+
aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
92+
docker tag $CONTAINER_IMAGE-prod:${{ github.sha }} $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:${{ github.sha }}
93+
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:${{ github.sha }}
94+
95+
deploy:
96+
name: Deploy automating-metadata
97+
needs:
98+
- build-and-push-images
99+
100+
runs-on: ubuntu-latest
101+
steps:
102+
- uses: hashicorp/setup-terraform@v1
103+
- name: Checkout
104+
uses: actions/checkout@v4
105+
106+
# Add steps here like linting, testing, minification, etc.
107+
- id: install-aws-cli
108+
uses: unfor19/install-aws-cli-action@v1
109+
with:
110+
version: 1
111+
112+
- uses: prepor/action-aws-iam-authenticator@master
113+
- run: aws-iam-authenticator version
114+
115+
- name: Install Kubectl
116+
run: |
117+
#$(curl -Ls https://dl.k8s.io/release/stable.txt)
118+
version=v1.23.6
119+
echo "using kubectl@$version"
120+
curl -sLO "https://dl.k8s.io/release/$version/bin/linux/amd64/kubectl" -o kubectl
121+
chmod +x kubectl
122+
mv kubectl /usr/local/bin
123+
mkdir $HOME/.kube
124+
sudo apt-get update
125+
sudo apt-get install less
126+
echo ${{ secrets.KUBE_CONFIG_DATA }} | base64 --decode > $HOME/.kube/config
127+
aws sts get-caller-identity
128+
129+
- name: Deploy to EKS (DEV)
130+
# uses: steebchen/kubectl@v2.0.0
131+
if: github.ref == 'refs/heads/develop'
132+
run: | # defaults to latest kubectl binary version
133+
kubectl apply -f desci-server/kubernetes/deployment_dev.yaml
134+
kubectl set image deployment/desci-server-dev desci-server-dev=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:${{ github.sha }} --record
135+
aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
136+
docker pull $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:${{ github.sha }}
137+
docker tag $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:${{ github.sha }} $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:latest
138+
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-dev:latest
139+
140+
- name: Deploy to EKS (PROD)
141+
if: github.ref == 'refs/heads/main'
142+
run: | # defaults to latest kubectl binary version
143+
kubectl apply -f desci-server/kubernetes/deployment_prod.yaml
144+
kubectl set image deployment/desci-server desci-server=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:${{ github.sha }} --record
145+
aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
146+
docker pull $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:${{ github.sha }}
147+
docker tag $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:${{ github.sha }} $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:latest
148+
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-prod:latest
149+
150+
- name: Verify EKS Deployment (DEV)
151+
if: github.ref == 'refs/heads/develop'
152+
run: |
153+
kubectl rollout status deployment/automating-metadata-dev
154+
155+
- name: Verify EKS Deployment (PROD)
156+
if: github.ref == 'refs/heads/main'
157+
run: |
158+
kubectl rollout status deployment/automating-metadata-prod
159+

DOCKERFILE

Lines changed: 0 additions & 20 deletions
This file was deleted.

Dockerfile

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Use a base image with Python installed
2+
FROM python:3.9
3+
4+
# Set the working directory in the container
5+
WORKDIR /
6+
7+
# we put this before the COPY app step just to cache the installation of the requirements, so if we make code changes without requirements updates builds are faster
8+
COPY ./app/requirements.txt ./app/requirements.txt
9+
RUN pip install -r ./app/requirements.txt
10+
11+
# Copy the script and requirements file into the container
12+
COPY ./app ./app
13+
14+
# Install dependencies
15+
RUN pip install gunicorn
16+
17+
#run service - Expose (what is the request response model)
18+
EXPOSE 5001
19+
EXPOSE 5005
20+
21+
ENV FLASK_APP=server.py
22+
23+
# Define the command to run when the container starts
24+
# CMD ["flask", "run", "--host=0.0.0.0", "--port=5001"]
25+
# gunicorn is a production ready web server for flask, with ability to handle multiple requests
26+
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5001", "app:server"]

app/requirements.txt

-28 Bytes
Binary file not shown.

app/server.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,9 @@ def invoke_script():
2727
output = run_langchain(pdf, cr_mailto, pyalex_email)
2828
return jsonify({'output': output})
2929

30+
@app.route('/', methods=['GET'])
31+
def index():
32+
return jsonify({'message': 'metadata server healthy'})
33+
3034
if __name__ == '__main__':
3135
app.run(host='0.0.0.0', port=5001)

kubernetes/deployment_dev.yaml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: automating-metadata-dev
5+
spec:
6+
selector:
7+
App: AutomatingMetadataDev
8+
ports:
9+
- port: 80
10+
targetPort: 5001
11+
type: ClusterIP
12+
---
13+
apiVersion: apps/v1
14+
kind: Deployment
15+
metadata:
16+
name: automating-metadata-dev
17+
labels:
18+
App: AutomatingMetadataDev
19+
spec:
20+
replicas: 2
21+
revisionHistoryLimit: 8
22+
selector:
23+
matchLabels:
24+
App: AutomatingMetadataDev
25+
strategy:
26+
rollingUpdate:
27+
maxSurge: 25%
28+
maxUnavailable: 25%
29+
type: RollingUpdate
30+
template:
31+
metadata:
32+
annotations:
33+
vault.hashicorp.com/agent-inject: 'true'
34+
vault.hashicorp.com/agent-inject-status: 'update'
35+
vault.hashicorp.com/role: app-vault-reader
36+
vault.hashicorp.com/agent-inject-secret-config: secrets/desci-server/staging/db
37+
vault.hashicorp.com/agent-inject-template-config: |
38+
{{- with secret "secrets/automating-metadata/dev" -}}
39+
export OPENAI_API_KEY={{ .Data.OPENAI_API_KEY }}
40+
export crmailto={{ .Data.crmailto }}
41+
export pyalexemail={{ .Data.pyalexemail }}
42+
export AM_API_KEY={{ .Data.AM_API_KEY }}
43+
export IPFS_GATEWAY_URL={{ .Data.IPFS_GATEWAY_URL }}
44+
45+
echo "dbset";
46+
{{- end -}}
47+
labels:
48+
App: AutomatingMetadataDev
49+
spec:
50+
containers:
51+
- image: 523044037273.dkr.ecr.us-east-2.amazonaws.com/automating-metadata-dev:latest
52+
name: automating-metadata-dev
53+
command: ['/bin/bash', '-c']
54+
args:
55+
- echo "SOURCING ENV"; source /vault/secrets/config; flask run --host=0.0.0.0 --port=5001
56+
ports:
57+
- containerPort: 5001
58+
name: server-api
59+
resources:
60+
limits:
61+
cpu: '1.0'
62+
memory: 5Gi
63+
requests:
64+
cpu: '0.8'
65+
memory: 5Gi
66+
# restart pod after failureThreshold*periodSeconds total seconds
67+
livenessProbe:
68+
httpGet:
69+
path: /
70+
port: server-api
71+
failureThreshold: 80
72+
periodSeconds: 3
73+
# temporarily stop sending traffic to pod after failureThreshold*periodSeconds total seconds
74+
readinessProbe:
75+
httpGet:
76+
path: /
77+
port: server-api
78+
failureThreshold: 3
79+
periodSeconds: 1
80+
# wait for pod to start for failureThreshold*periodSeconds total seconds
81+
startupProbe:
82+
httpGet:
83+
path: /
84+
port: server-api
85+
failureThreshold: 200
86+
periodSeconds: 1
87+
serviceAccountName: 'vault-auth'

kubernetes/deployment_prod.yaml

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: automating-metadata-prod
5+
spec:
6+
selector:
7+
App: AutomatingMetadataProd
8+
ports:
9+
- port: 80
10+
targetPort: 5001
11+
type: ClusterIP
12+
---
13+
apiVersion: apps/v1
14+
kind: Deployment
15+
metadata:
16+
name: automating-metadata-prod
17+
labels:
18+
App: AutomatingMetadataProd
19+
spec:
20+
replicas: 2
21+
revisionHistoryLimit: 8
22+
selector:
23+
matchLabels:
24+
App: AutomatingMetadataProd
25+
strategy:
26+
rollingUpdate:
27+
maxSurge: 25%
28+
maxUnavailable: 25%
29+
type: RollingUpdate
30+
template:
31+
metadata:
32+
annotations:
33+
vault.hashicorp.com/agent-inject: 'true'
34+
vault.hashicorp.com/agent-inject-status: 'update'
35+
vault.hashicorp.com/role: app-vault-reader
36+
vault.hashicorp.com/agent-inject-secret-config: secrets/desci-server/staging/db
37+
vault.hashicorp.com/agent-inject-template-config: |
38+
{{- with secret "secrets/automating-metadata/prod" -}}
39+
export OPENAI_API_KEY={{ .Data.OPENAI_API_KEY }}
40+
export crmailto={{ .Data.crmailto }}
41+
export pyalexemail={{ .Data.pyalexemail }}
42+
export AM_API_KEY={{ .Data.AM_API_KEY }}
43+
export IPFS_GATEWAY_URL={{ .Data.IPFS_GATEWAY_URL }}
44+
45+
echo "dbset";
46+
{{- end -}}
47+
labels:
48+
App: AutomatingMetadataProd
49+
spec:
50+
containers:
51+
- image: 523044037273.dkr.ecr.us-east-2.amazonaws.com/automating-metadata-prod:latest
52+
name: automating-metadata-prod
53+
command: ['/bin/bash', '-c']
54+
args:
55+
- echo "SOURCING ENV"; source /vault/secrets/config; flask run --host=0.0.0.0 --port=5001
56+
ports:
57+
- containerPort: 5001
58+
name: server-api
59+
resources:
60+
limits:
61+
cpu: '1.0'
62+
memory: 5Gi
63+
requests:
64+
cpu: '0.8'
65+
memory: 5Gi
66+
# restart pod after failureThreshold*periodSeconds total seconds
67+
livenessProbe:
68+
httpGet:
69+
path: /
70+
port: server-api
71+
failureThreshold: 80
72+
periodSeconds: 3
73+
# temporarily stop sending traffic to pod after failureThreshold*periodSeconds total seconds
74+
readinessProbe:
75+
httpGet:
76+
path: /
77+
port: server-api
78+
failureThreshold: 3
79+
periodSeconds: 1
80+
# wait for pod to start for failureThreshold*periodSeconds total seconds
81+
startupProbe:
82+
httpGet:
83+
path: /
84+
port: server-api
85+
failureThreshold: 200
86+
periodSeconds: 1
87+
serviceAccountName: 'vault-auth'

0 commit comments

Comments
 (0)