Created
March 28, 2022 12:53
-
-
Save mtsmfm/807a5c3575c2b6376d5d76cfda7d0ace to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'bundler/inline' | |
gemfile do | |
source 'https://rubygems.org' | |
gem 'pry-byebug' | |
gem 'activesupport', require: %w[active_support active_support/core_ext/hash] | |
end | |
require "open3" | |
require "yaml" | |
require "fileutils" | |
require "pathname" | |
require "erb" | |
output, status = Open3.capture2("docker compose convert") | |
k8s_dir = Pathname.new(__dir__).join("k8s") | |
services = YAML.load(output)["services"] | |
all_env_var_values = services.values.flat_map {|v| v['environment']&.values }.uniq.compact | |
services.each do |service, definition| | |
deployment_file = k8s_dir.join("deployment").join("#{service}.yaml") | |
FileUtils.mkdir_p(deployment_file.dirname) | |
deployment = { | |
apiVersion: 'apps/v1', | |
kind: 'Deployment', | |
metadata: { | |
labels: {app: service}, | |
name: service, | |
}, | |
spec: { | |
replicas: 1, | |
selector: { | |
matchLabels: { | |
app: service, | |
} | |
}, | |
template: { | |
metadata: { | |
labels: {app: service} | |
}, | |
spec: { | |
containers: [ | |
image: definition['image'], | |
name: service, | |
] | |
} | |
} | |
} | |
}.deep_stringify_keys | |
container = deployment['spec']['template']['spec']['containers'][0] | |
if definition['entrypoint'] | |
container['command'] = definition['entrypoint'] | |
end | |
if definition['command'] | |
container['args'] = definition['command'] | |
end | |
if definition['volumes'] | |
container['volumeMounts'] = definition['volumes'].map do |v| | |
case v['type'] | |
when 'bind' | |
{ | |
mountPath: v['target'], | |
name: 'sentry-volume', | |
subPath: "self-hosted/#{Pathname.new(v['source']).relative_path_from(Dir.pwd)}", | |
readOnly: !!v['read_only'] | |
} | |
when 'volume' | |
{ | |
mountPath: v['target'], | |
name: 'sentry-volume', | |
subPath: v['source'], | |
} | |
end | |
end | |
deployment['spec']['template']['spec']['volumes'] = [ | |
name: 'sentry-volume', | |
persistentVolumeClaim: {claimName: 'sentry-volume'} | |
] | |
end | |
if definition['environment'] | |
container['env'] = definition['environment'].map do |k, v| | |
{name: k, value: k == 'SENTRY_MAIL_HOST' ? 'localhost' : v} | |
end | |
end | |
if service == 'web' | |
deployment['spec']['template']['spec']['initContainers'] = [ | |
{ | |
name: 'init', | |
image: 'alpine/git', | |
command: ['sh', '-c', <<~COMMAND], | |
set -x | |
git clone https://github.com/getsentry/self-hosted /tmp/self-hosted | |
cd /sentry-volume/self-hosted | |
mkdir -p sentry | |
cp /tmp/self-hosted/sentry/config.example.yml sentry/config.yml | |
SECRET_KEY=secret | |
sed -i -e 's/^system.secret-key:.*$/system.secret-key: '"'$SECRET_KEY'"'/' sentry/config.yml | |
cp /tmp/self-hosted/sentry/requirements.example.txt sentry/requirements.txt | |
cp /tmp/self-hosted/sentry/sentry.conf.example.py sentry/sentry.conf.py | |
mkdir -p symbolicator | |
cp /tmp/self-hosted/symbolicator/config.example.yml symbolicator/config.yml | |
mkdir -p relay | |
cp /tmp/self-hosted/relay/config.example.yml relay/config.yml | |
echo '{"secret_key":"secret","public_key":"public","id":"id"}' > relay/credentials.json | |
mkdir -p geoip | |
cp /tmp/self-hosted/geoip/GeoLite2-City.mmdb.empty geoip/GeoLite2-City.mmdb | |
mkdir -p postgres/wal2json | |
wget https://github.com/getsentry/wal2json/releases/download/0.0.2/wal2json-Linux-x86_64-glibc.so -O postgres/wal2json/wal2json.so | |
cp /tmp/self-hosted/postgres/*.sh postgres | |
COMMAND | |
volumeMounts: [ | |
mountPath: '/sentry-volume', | |
name: 'sentry-volume', | |
] | |
}, | |
{ | |
name: 'init-2', | |
image: definition['image'], | |
command: ['bash', '-c', <<~COMMAND], | |
set -x | |
until echo < /dev/tcp/postgres/5432; do | |
sleep 1 | |
done | |
until echo < /dev/tcp/memcached/11211; do | |
sleep 1 | |
done | |
/docker-entrypoint.sh upgrade | |
COMMAND | |
volumeMounts: container['volumeMounts'] | |
} | |
] | |
elsif service == 'postgres' | |
deployment['spec']['template']['spec']['initContainers'] = [ | |
name: 'init', | |
image: definition['image'], | |
command: ['bash', '-c', <<~COMMAND], | |
set -x | |
until [ -f /opt/sentry/wal2json/wal2json.so ]; do | |
sleep 1 | |
done | |
COMMAND | |
volumeMounts: container['volumeMounts'] | |
] | |
elsif %w(redis).include?(service) | |
deployment['spec']['template']['spec']['initContainers'] = [ | |
name: 'wait-clone', | |
image: 'alpine/git', | |
command: ['sh', '-c', <<~COMMAND], | |
set -x | |
until [ -d /sentry-volume/self-hosted ]; do | |
sleep 1 | |
done | |
COMMAND | |
volumeMounts: [ | |
mountPath: '/sentry-volume', | |
name: 'sentry-volume', | |
] | |
] | |
else | |
deployment['spec']['template']['spec']['initContainers'] = [ | |
name: 'wait-web', | |
image: 'busybox:1.28', | |
command: ['sh', '-c', "until curl web:9000; do echo waiting for web; sleep 2; done"] | |
] | |
end | |
deployment_file.write(deployment.deep_stringify_keys.to_yaml) | |
end | |
{ | |
web: 9000, | |
relay: 3000, | |
'snuba-api': 1218, | |
kafka: 9092, | |
zookeeper: 2181, | |
redis: 6379, | |
postgres: 5432, | |
memcached: 11211, | |
clickhouse: 8123, | |
nginx: 80, | |
}.each do |name, port| | |
name = name.to_s | |
service_file = k8s_dir.join("service").join("#{name}.yaml") | |
service = { | |
apiVersion: 'v1', | |
kind: 'Service', | |
metadata: {name: name}, | |
spec: { | |
ports: [port: port, protocol: 'TCP'], | |
type: 'ClusterIP', | |
selector: {app: name} | |
} | |
} | |
FileUtils.mkdir_p(service_file.dirname) | |
service_file.write(service.deep_stringify_keys.to_yaml) | |
end | |
ingress_file = k8s_dir.join("ingress").join("ingress.yaml") | |
FileUtils.mkdir_p(ingress_file.dirname) | |
ingress = { | |
apiVersion: 'networking.k8s.io/v1', | |
kind: 'Ingress', | |
metadata: { | |
name: 'nginx' | |
}, | |
spec: { | |
ingressClassName: 'nginx', | |
rules: [ | |
host: 'sentry.localhost', | |
http: { | |
paths: [ | |
path: "/", | |
pathType: 'Prefix', | |
backend: { | |
service: { | |
name: 'nginx', | |
port: { | |
number: 80 | |
} | |
} | |
} | |
] | |
} | |
] | |
} | |
} | |
ingress_file.write(ingress.deep_stringify_keys.to_yaml) | |
pvc_file = k8s_dir.join("pvc").join("pvc.yaml") | |
FileUtils.mkdir_p(pvc_file.dirname) | |
pvc = { | |
apiVersion: 'v1', | |
kind: 'PersistentVolumeClaim', | |
metadata: { | |
name: 'sentry-volume' | |
}, | |
spec: { | |
accessModes: ['ReadWriteOnce'], | |
storageClassName: 'local-path', | |
resources: { | |
requests: { | |
storage: '10Gi' | |
} | |
} | |
} | |
} | |
pvc_file.write(pvc.deep_stringify_keys.to_yaml) | |
kustomization_file = k8s_dir.join("kustomization.yaml") | |
kustomization = { | |
apiVersion: 'kustomize.config.k8s.io/v1beta1', | |
kind: 'Kustomization', | |
resources: k8s_dir.glob('*/*.yaml').map {|file| file.relative_path_from(k8s_dir).to_s } | |
} | |
kustomization_file.write(kustomization.deep_stringify_keys.to_yaml) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment