Skip to content

Commit 9ccbc77

Browse files
committed
Add skypilot
1 parent 50d5084 commit 9ccbc77

File tree

12 files changed

+511
-0
lines changed

12 files changed

+511
-0
lines changed

charts/stable/skypilot/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Chart.lock
2+
charts/

charts/stable/skypilot/.helmignore

Whitespace-only changes.

charts/stable/skypilot/Chart.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
apiVersion: v2
2+
name: skypilot
3+
description: A Helm chart for deploying SkyPilot API server on Kubernetes
4+
type: application
5+
version: 0.0.1-pre-01
6+
appVersion: "0.0"
7+
dependencies:
8+
- name: ingress-nginx
9+
version: 4.11.3
10+
repository: https://kubernetes.github.io/ingress-nginx
11+
condition: ingress-nginx.enabled
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{- if .Values.apiService.config }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: {{ .Release.Name }}-config
6+
namespace: {{ .Release.Namespace }}
7+
data:
8+
config.yaml: |
9+
{{ .Values.apiService.config | indent 4 }}
10+
{{- end }}
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: {{ .Release.Name }}-api-server
5+
namespace: {{ .Release.Namespace }}
6+
spec:
7+
# Note: replicas > 1 is not well tested, and requires a PVC that supports ReadWriteMany.
8+
replicas: {{ .Values.apiService.replicas }}
9+
strategy:
10+
type: Recreate
11+
selector:
12+
matchLabels:
13+
app: {{ .Release.Name }}-api
14+
template:
15+
metadata:
16+
labels:
17+
app: {{ .Release.Name }}-api
18+
spec:
19+
automountServiceAccountToken: {{ .Values.kubernetesCredentials.useApiServerCluster }}
20+
serviceAccountName: {{ .Release.Name }}-api-sa
21+
{{- with $.Values.podSecurityContext }}
22+
securityContext:
23+
{{- toYaml . | nindent 8 }}
24+
{{- end }}
25+
containers:
26+
- name: skypilot-api
27+
image: {{ .Values.apiService.image }}
28+
imagePullPolicy: Always
29+
{{- with $.Values.securityContext }}
30+
securityContext:
31+
{{- toYaml . | nindent 10 }}
32+
{{- end }}
33+
resources:
34+
{{- toYaml .Values.apiService.resources | nindent 10 }}
35+
env:
36+
- name: SKYPILOT_DEV
37+
value: {{ .Values.apiService.skypilotDev | quote }}
38+
{{- if .Values.gcpCredentials.enabled }}
39+
- name: GOOGLE_APPLICATION_CREDENTIALS
40+
value: /root/gcp-cred.json
41+
{{- end }}
42+
{{- if .Values.kubernetesCredentials.inclusterNamespace }}
43+
- name: SKYPILOT_IN_CLUSTER_NAMESPACE
44+
value: {{ .Values.kubernetesCredentials.inclusterNamespace }}
45+
{{- end }}
46+
# Use tini as the init process
47+
command: ["tini", "--"]
48+
# Start API server in foreground (if supported) to:
49+
# 1. Bypass the healthz check of `sky api start`, let kubernetes probes manage the lifecycle directly.
50+
# 2. Capture all logs in container to stdout/stderr, bypass in-container log file overhead.
51+
# 3. Exec ensures the process is a direct child of tini, enables correct signal handling.
52+
# Note: this comment is moved here to avoid appearing in the final start script.
53+
args:
54+
- /bin/sh
55+
- -c
56+
- |
57+
set -e
58+
{{- if .Values.apiService.preDeployHook }}
59+
{{ .Values.apiService.preDeployHook | nindent 10 }}
60+
{{- end }}
61+
{{- if .Values.apiService.config }}
62+
mkdir -p /root/.sky
63+
echo "Copying config.yaml from ConfigMap \`skypilot-config\` to /root/.sky/config.yaml"
64+
# The configmap serves as the ground truth for the config.yaml file.
65+
# Any local changes to the config.yaml file will be overwritten by the contents of the configmap.
66+
cp /tmp/config.yaml /root/.sky/config.yaml
67+
{{- end }}
68+
69+
if sky api start -h | grep -q -- "--foreground"; then
70+
exec sky api start --deploy --foreground
71+
else
72+
# For backward compatibility, run in background if --foreground is not supported.
73+
# TODO(aylei): this will bedropped in 0.11.0.
74+
if sky api start --deploy; then
75+
tail -n+0 -f /root/.sky/api_server/server.log
76+
else
77+
cat /root/.sky/api_server/server.log
78+
fi
79+
fi
80+
ports:
81+
- containerPort: 46580
82+
livenessProbe:
83+
httpGet:
84+
path: /api/health
85+
port: 46580
86+
periodSeconds: 30
87+
readinessProbe:
88+
httpGet:
89+
path: /api/health
90+
port: 46580
91+
periodSeconds: 30
92+
volumeMounts:
93+
{{- if .Values.storage.enabled }}
94+
- name: state-volume
95+
mountPath: /root/.sky
96+
subPath: .sky
97+
- name: state-volume
98+
mountPath: /root/.ssh # To preserve the SSH keys for the user when using the API server
99+
subPath: .ssh
100+
{{- end }}
101+
{{- if .Values.apiService.config }}
102+
- name: skypilot-config
103+
mountPath: /tmp/config.yaml
104+
subPath: config.yaml
105+
{{- end }}
106+
{{- if .Values.awsCredentials.enabled }}
107+
- name: aws-config
108+
mountPath: /root/.aws
109+
readOnly: true
110+
{{- end }}
111+
{{- if .Values.gcpCredentials.enabled }}
112+
- name: gcp-config
113+
mountPath: /root/.config/gcloud
114+
- name: gcp-credentials
115+
mountPath: /root/gcp-cred.json
116+
subPath: gcp-cred.json
117+
{{- end }}
118+
{{- if .Values.kubernetesCredentials.useKubeconfig }}
119+
- name: kube-config
120+
mountPath: /root/.kube
121+
{{- end }}
122+
initContainers:
123+
{{- if .Values.awsCredentials.enabled }}
124+
- name: create-aws-credentials
125+
image: {{ .Values.apiService.image }}
126+
command: ["/bin/sh", "-c"]
127+
args:
128+
- |
129+
echo "Setting up AWS credentials..."
130+
if [ -n "$AWS_ACCESS_KEY_ID" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ]; then
131+
echo "AWS credentials found in environment variables."
132+
aws configure set aws_access_key_id "$AWS_ACCESS_KEY_ID"
133+
aws configure set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY"
134+
echo "Credentials file created successfully."
135+
else
136+
echo "AWS credentials not found in environment variables. Skipping credentials setup."
137+
sleep 600
138+
fi
139+
env:
140+
- name: AWS_ACCESS_KEY_ID
141+
valueFrom:
142+
secretKeyRef:
143+
name: aws-credentials
144+
key: aws_access_key_id
145+
- name: AWS_SECRET_ACCESS_KEY
146+
valueFrom:
147+
secretKeyRef:
148+
name: aws-credentials
149+
key: aws_secret_access_key
150+
volumeMounts:
151+
- name: aws-config
152+
mountPath: /root/.aws
153+
{{- end }}
154+
{{- if .Values.gcpCredentials.enabled }}
155+
- name: setup-gcp-credentials
156+
image: google/cloud-sdk:latest
157+
command: ["/bin/sh", "-c"]
158+
env:
159+
- name: GOOGLE_APPLICATION_CREDENTIALS
160+
value: /root/gcp-cred.json
161+
args:
162+
- |
163+
gcloud auth activate-service-account --key-file=/root/gcp-cred.json
164+
gcloud config set project {{ .Values.gcpCredentials.projectId }}
165+
volumeMounts:
166+
- name: gcp-credentials
167+
mountPath: /root/gcp-cred.json
168+
subPath: gcp-cred.json
169+
- name: gcp-config
170+
mountPath: /root/.config/gcloud
171+
{{- end }}
172+
volumes:
173+
{{- if .Values.storage.enabled }}
174+
- name: state-volume
175+
persistentVolumeClaim:
176+
claimName: {{ .Release.Name }}-state
177+
{{- else }}
178+
- name: state-volume
179+
emptyDir: {}
180+
{{- end }}
181+
{{- if .Values.awsCredentials.enabled }}
182+
- name: aws-config
183+
emptyDir: {}
184+
{{- end }}
185+
186+
{{- if .Values.gcpCredentials.enabled }}
187+
- name: gcp-credentials
188+
secret:
189+
secretName: gcp-credentials
190+
- name: gcp-config
191+
emptyDir: {}
192+
{{- end }}
193+
{{- if .Values.kubernetesCredentials.useKubeconfig }}
194+
- name: kube-config
195+
secret:
196+
secretName: {{ .Values.kubernetesCredentials.kubeconfigSecretName }}
197+
{{- end }}
198+
{{- if .Values.apiService.config }}
199+
- name: skypilot-config
200+
configMap:
201+
name: {{ .Release.Name }}-config
202+
{{- end }}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: {{ .Release.Name }}-api-service
5+
namespace: {{ .Release.Namespace }}
6+
spec:
7+
type: ClusterIP # Use clusterIP to allow ingress to authenticate
8+
ports:
9+
- port: 80
10+
targetPort: 46580 # Assuming your container listens on port 46580
11+
protocol: TCP
12+
selector:
13+
app: {{ .Release.Name }}-api
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{- if and (not .Values.ingress.authSecret) .Values.ingress.authCredentials }}
2+
apiVersion: v1
3+
kind: Secret
4+
metadata:
5+
name: {{ .Release.Name }}-basic-auth
6+
namespace: {{ .Release.Namespace }}
7+
type: Opaque
8+
stringData:
9+
auth: {{ .Values.ingress.authCredentials | quote }}
10+
{{- end }}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{{- if and .Values.ingress.nodePortEnabled (index .Values "ingress-nginx" "enabled") }}
2+
apiVersion: v1
3+
kind: Service
4+
metadata:
5+
name: {{ .Release.Name }}-ingress-controller-np
6+
namespace: {{ .Release.Namespace }}
7+
spec:
8+
type: NodePort
9+
ports:
10+
- port: 80
11+
targetPort: 80
12+
{{- if .Values.ingress.httpNodePort }}
13+
nodePort: {{ .Values.ingress.httpNodePort }}
14+
{{- end }}
15+
name: http
16+
- port: 443
17+
targetPort: 443
18+
{{- if .Values.ingress.httpsNodePort }}
19+
nodePort: {{ .Values.ingress.httpsNodePort }}
20+
{{- end }}
21+
name: https
22+
selector:
23+
app.kubernetes.io/component: controller
24+
app.kubernetes.io/instance: {{ .Release.Name }}
25+
app.kubernetes.io/name: ingress-nginx
26+
{{- end}}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{{- if .Values.ingress.enabled }}
2+
{{- $kubeVersion := .Capabilities.KubeVersion.Major -}}
3+
{{- $kubeMinorVersion := .Capabilities.KubeVersion.Minor | trimSuffix "+" | int -}}
4+
{{- $useNewIngressClass := or (gt ($kubeVersion | int) 1) (and (eq ($kubeVersion | int) 1) (ge $kubeMinorVersion 18)) -}}
5+
6+
apiVersion: networking.k8s.io/v1
7+
kind: Ingress
8+
metadata:
9+
name: {{ .Release.Name }}-ingress
10+
namespace: {{ .Release.Namespace }}
11+
annotations:
12+
{{- if not $useNewIngressClass }}
13+
kubernetes.io/ingress.class: nginx
14+
{{- end }}
15+
nginx.ingress.kubernetes.io/auth-type: basic
16+
nginx.ingress.kubernetes.io/auth-secret: {{ .Values.ingress.authSecret | default (printf "%s-basic-auth" .Release.Name) }}
17+
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
18+
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
19+
nginx.ingress.kubernetes.io/proxy-body-size: "1000m"
20+
{{- if ne .Values.ingress.path "/" }}
21+
nginx.ingress.kubernetes.io/rewrite-target: /$2
22+
{{- end }}
23+
nginx.ingress.kubernetes.io/server-snippets: |
24+
location / {
25+
proxy_set_header Upgrade $http_upgrade;
26+
proxy_http_version 1.1;
27+
proxy_set_header X-Forwarded-Host $http_host;
28+
proxy_set_header X-Forwarded-Proto $scheme;
29+
proxy_set_header X-Forwarded-For $remote_addr;
30+
proxy_set_header Host $host;
31+
proxy_set_header Connection "upgrade";
32+
proxy_cache_bypass $http_upgrade;
33+
}
34+
35+
36+
spec:
37+
{{- if $useNewIngressClass }}
38+
ingressClassName: nginx
39+
{{- end }}
40+
rules:
41+
- http:
42+
paths:
43+
{{- /* TODO(aylei): check whether this works for ingress-controllers other than nginx */}}
44+
- pathType: {{ if eq .Values.ingress.path "/" }}Prefix{{ else }}ImplementationSpecific{{ end }}
45+
path: {{ .Values.ingress.path }}{{ if ne .Values.ingress.path "/" }}(/|$)(.*){{ end }}
46+
backend:
47+
service:
48+
name: {{ .Release.Name }}-api-service
49+
port:
50+
number: 80
51+
{{- end }}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{{- if .Values.storage.enabled }}
2+
apiVersion: v1
3+
kind: PersistentVolumeClaim
4+
metadata:
5+
name: {{ .Release.Name }}-state
6+
namespace: {{ .Release.Namespace }}
7+
{{- with .Values.storage.annotations }}
8+
annotations:
9+
{{- toYaml . | nindent 4 }}
10+
{{- end }}
11+
spec:
12+
{{- if .Values.storage.storageClassName }}
13+
storageClassName: {{ .Values.storage.storageClassName }}
14+
{{- end }}
15+
{{- if .Values.storage.volumeName }}
16+
volumeName: {{ .Values.storage.volumeName }}
17+
{{- end }}
18+
accessModes:
19+
- {{ .Values.storage.accessMode }}
20+
resources:
21+
requests:
22+
storage: {{ .Values.storage.size }}
23+
{{- with .Values.storage.selector }}
24+
selector:
25+
{{- toYaml . | nindent 4 }}
26+
{{- end }}
27+
{{- end }}

0 commit comments

Comments
 (0)