Skip to content

Instantly share code, notes, and snippets.

@mtsmfm
Created March 28, 2022 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mtsmfm/807a5c3575c2b6376d5d76cfda7d0ace to your computer and use it in GitHub Desktop.
Save mtsmfm/807a5c3575c2b6376d5d76cfda7d0ace to your computer and use it in GitHub Desktop.
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