Created
March 28, 2022 12:53
-
-
Save mtsmfm/807a5c3575c2b6376d5d76cfda7d0ace to your computer and use it in GitHub Desktop.
This file contains hidden or 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