Package: kubragen2
KubraGen2: programmatic Kubernetes YAML generatorKubraGen2 is a Kubernetes YAML generator library that makes it possible to generate
configurations using the full power of the Python programming language.Combined withHelmion, it is possible to useHelmas a Kubernetes Yaml source, customize them, and generate a script for applying it directly without using
the Helm release process.SeeKubragen2 Samplesfor real-life examples.OverviewSee source code for examplesWebsite:https://github.com/RangelReale/kubragen2Repository:https://github.com/RangelReale/kubragen2.gitDocumentation:https://kubragen2.readthedocs.org/PyPI:https://pypi.python.org/pypi/kubragen2Exampleimportargparseimportdatetimeimportosfromhelmion.chartimportProcessorChain,Chartfromhelmion.helmchartimportHelmRequestfromhelmion.processorimportDefaultProcessor,FilterRemoveHelmData,ListSplitterfromhelmion.resourceimportis_any_resourcefromkubragen2.buildimportBuildDatafromkubragen2.dataimportValueDatafromkubragen2.kdataimportKData_PersistentVolume_HostPath,KData_PersistentVolumeClaim,\KData_PersistentVolumeClaim_NoSelector,KData_PersistentVolume_Request,KData_PersistentVolume_CSI,\KData_PersistentVolumeClaim_Requestfromkubragen2.outputimportOutputProject,OutputFile_ShellScript,OutputFile_Kubernetes,OD_FileTemplate,\OutputDriver_Directoryfromkubragen2.provider.awsimportKData_PersistentVolume_CSI_AWSEBSfromkubragen2.provider.digitaloceanimportKData_PersistentVolume_CSI_DOBSfromkubragen2.provider.gcloudimportKData_PersistentVolume_GCEPersistentDiskdefmain():parser=argparse.ArgumentParser(description='Kube Creator')parser.add_argument('-p','--provider',help='provider',required=True,choices=['google-gke','amazon-eks','digitalocean-kubernetes','k3d',])parser.add_argument('--no-resource-limit',help='don''t limit resources',action='store_true')parser.add_argument('-o','--output-path',help='output path',default='output')args=parser.parse_args()## Persistent Volumes#pv_volumes=Nonepvc_volumes=Noneifargs.provider=='k3d':pv_volumes=KData_PersistentVolume_HostPath()pvc_volumes=KData_PersistentVolumeClaim_NoSelector()elifargs.provider=='google-gke':pv_volumes=KData_PersistentVolume_GCEPersistentDisk()elifargs.provider=='digitalocean-kubernetes':pv_volumes=KData_PersistentVolume_CSI_DOBS()elifargs.provider=='amazon-eks':pv_volumes=KData_PersistentVolume_CSI_AWSEBS()else:raiseException('Unknown target')ifpvc_volumesisNone:pvc_volumes=KData_PersistentVolumeClaim()## Volumes#pv_prometheus_files=KData_PersistentVolume_Request(name='prometheus-storage',selector_labels={'pv.role':'prometheus',},storageclassname='',storage='50Gi',access_modes=['ReadWriteOnce'],configs=[KData_PersistentVolume_HostPath.Config(hostpath={'path':'/var/storage/prometheus'}),KData_PersistentVolume_CSI.Config(csi={'fsType':'ext4'}),])pvc_prometheus_files=KData_PersistentVolumeClaim_Request(name='prometheus-claim',namespace='monitoring',pvreq=pv_prometheus_files,)# Add namespace to items, and filter Helm data from labels and annotationshelm_default_processor=ProcessorChain(DefaultProcessor(add_namespace=True),FilterRemoveHelmData())defhelm_splitter_crd(cat,chart,data):returnis_any_resource(data,{'apiVersionNS':'apiextensions.k8s.io','kind':'CustomResourceDefinition'})defhelm_splitter_config(cat,chart,data):returnis_any_resource(data,{'apiVersionNS':'rbac.authorization.k8s.io'},{'apiVersionNS':'policy'},{'apiVersionNS':'','kind':'ServiceAccount'},{'apiVersionNS':'','kind':'Secret'},{'apiVersionNS':'','kind':'ConfigMap'},{'apiVersionNS':'monitoring.coreos.com'},{'apiVersionNS':'admissionregistration.k8s.io'},)defhelm_splitter_job(cat,chart,data):returnis_any_resource(data,{'apiVersionNS':'batch'})defhelm_splitter_service(cat,chart,data):returnis_any_resource(data,{'apiVersionNS':'','kind':'Service'},{'apiVersionNS':'','kind':'Pod'},{'apiVersionNS':'','kind':'List'},{'apiVersionNS':'apps','kind':'Deployment'},{'apiVersionNS':'apps','kind':'DaemonSet'},{'apiVersionNS':'apps','kind':'StatefulSet'})# Start outputout=OutputProject()shell_script=OutputFile_ShellScript('create_{}.sh'.format(args.provider))out.append(shell_script)shell_script.append('set -e')## Provider setup#ifargs.provider=='k3d':storage_directory=os.path.join(os.getcwd(),'output','storage')ifnotos.path.exists(storage_directory):os.makedirs(storage_directory)ifnotos.path.exists(os.path.join(storage_directory,'prometheus')):os.makedirs(os.path.join(storage_directory,'prometheus'))shell_script.append(f'# k3d cluster create kg2sample-prometheus-stack --port 5051:80@loadbalancer --port 5052:443@loadbalancer -v{storage_directory}:/var/storage')## OUTPUTFILE: namespace.yaml#file=OutputFile_Kubernetes('namespace.yaml')file.append([{'apiVersion':'v1','kind':'Namespace','metadata':{'name':'monitoring',},}])out.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: storage.yaml#file=OutputFile_Kubernetes('storage.yaml')file.append(pv_volumes.build(pv_prometheus_files))# file.append(pv_volumes.build_claim(pvc_volumes, pvc_prometheus_files)) # this will be used only as spec in Helmout.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## HELM: traefik2#helmreq=HelmRequest(repository='https://helm.traefik.io/traefik',chart='traefik',version='9.11.0',releasename='traefik-router',# rename to avoid conflict with k3dnamespace='monitoring',values=BuildData({'ingressRoute':{'dashboard':{'enabled':False,}},'providers':{'kubernetesCRD':{'enabled':True,'namespaces':['default','monitoring',]},'kubernetesIngress':{'enabled':False,}},'logs':{'access':{'enabled':True,}},'globalArguments':['--global.checkNewVersion=false','--global.sendAnonymousUsage=false',],'additionalArguments':['--api.debug=true','--api.dashboard=true','--api.insecure=false','--metrics.prometheus=true','--metrics.prometheus.entryPoint=metrics','--metrics.prometheus.addEntryPointsLabels=true',],'ports':{'web':{'expose':True,'exposedPort':80,},'websecure':{'expose':False,},'api':{'port':8080,'expose':True,},'metrics':{'expose':True,'port':9090,},},'service':{'type':'NodePort'ifargs.provider!='k3d'else'ClusterIP',},'resources':ValueData(value={'requests':{'cpu':'100m','memory':'200Mi',},'limits':{'cpu':'200m','memory':'300Mi',},},enabled=notargs.no_resource_limit),}))traefik_helmchart=helmreq.generate().process(helm_default_processor).split(ListSplitter({'crd':helm_splitter_crd,'config':helm_splitter_config,'service':helm_splitter_service,},exactly_one_category=True))## OUTPUTFILE: traefik-config-crd.yaml#file=OutputFile_Kubernetes('traefik-config-crd.yaml')file.append(traefik_helmchart['crd'].data)out.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: traefik-config.yaml#file=OutputFile_Kubernetes('traefik-config.yaml')file.append(traefik_helmchart['config'].data)file.append([{'apiVersion':'traefik.containo.us/v1alpha1','kind':'IngressRoute','metadata':{'name':'traefik-api','namespace':'monitoring',},'spec':{'entryPoints':['api'],'routes':[{'match':'Method(`GET`)','kind':'Rule','services':[{'name':'api@internal','kind':'TraefikService'}]}]}}])out.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## HELM: prometheus#helmreq=HelmRequest(repository='https://prometheus-community.github.io/helm-charts',chart='kube-prometheus-stack',version='12.2.3',releasename='kube-prometheus-stack',namespace='monitoring',values=BuildData({'alertmanager':{'resources':ValueData(value={'requests':{'cpu':'50m','memory':'100Mi'},'limits':{'cpu':'100m','memory':'150Mi',},},enabled=notargs.no_resource_limit),},'grafana':{'enabled':True,'adminPassword':'grafana123','resources':ValueData(value={'requests':{'cpu':'50m','memory':'100Mi'},'limits':{'cpu':'100m','memory':'128Mi',},},enabled=notargs.no_resource_limit),},'prometheusOperator':{'enabled':True,'resources':ValueData(value={'requests':{'cpu':'50m','memory':'50Mi'},'limits':{'cpu':'120m','memory':'120Mi'},},enabled=notargs.no_resource_limit),},'kube-state-metrics':{'resources':ValueData(value={'requests':{'cpu':'10m','memory':'32Mi',},'limits':{'cpu':'100m','memory':'64Mi',}},enabled=notargs.no_resource_limit),},'prometheus-node-exporter':{'resources':ValueData(value={'requests':{'cpu':'150m','memory':'150Mi',},'limits':{'cpu':'200m','memory':'200Mi'},},enabled=notargs.no_resource_limit),},'prometheus':{'service':{'port':80,},'prometheusSpec':{'containers':[{'name':'prometheus','readinessProbe':{'initialDelaySeconds':30,'periodSeconds':30,'timeoutSeconds':8,},}],'resources':ValueData(value={'requests':{'cpu':'150m','memory':'350Mi'},'limits':{'cpu':'300m','memory':'800Mi'},},enabled=notargs.no_resource_limit),'storageSpec':{'volumeClaimTemplate':{'spec':pv_volumes.build_claim(pvc_volumes,pvc_prometheus_files)['spec'],},}}},'coreDns':{'enabled':args.provider!='google-gke',},'kubeDns':{'enabled':args.provider=='google-gke',},}))prometheus_helmchart=helmreq.generate().process(helm_default_processor).split(ListSplitter({'crd':helm_splitter_crd,'config':helm_splitter_config,'job':helm_splitter_job,'service':helm_splitter_service,},exactly_one_category=True))## OUTPUTFILE: prometheus-crd.yaml#file=OutputFile_Kubernetes('prometheus-crd.yaml')out.append(file)file.append(prometheus_helmchart['crd'].data)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: prometheus-config.yaml#file=OutputFile_Kubernetes('prometheus-config.yaml')out.append(file)file.append(prometheus_helmchart['config'].data)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: prometheus-job.yaml#file=OutputFile_Kubernetes('prometheus-job.yaml')out.append(file)file.append(prometheus_helmchart['job'].data)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: prometheus.yaml#file=OutputFile_Kubernetes('prometheus.yaml')out.append(file)file.append(prometheus_helmchart['service'].data)file.append([{'apiVersion':'traefik.containo.us/v1alpha1','kind':'IngressRoute','metadata':{'name':'admin-prometheus','namespace':'monitoring',},'spec':{'entryPoints':['web'],'routes':[{'match':f'Host(`admin-prometheus.localdomain`)','kind':'Rule','services':[{'name':'kube-prometheus-stack-prometheus','namespace':'monitoring','port':80,}],}]}},{'apiVersion':'traefik.containo.us/v1alpha1','kind':'IngressRoute','metadata':{'name':'admin-grafana','namespace':'monitoring',},'spec':{'entryPoints':['web'],'routes':[{'match':f'Host(`admin-grafana.localdomain`)','kind':'Rule','services':[{'name':'kube-prometheus-stack-grafana','namespace':'monitoring','port':80,}],}]}}])shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: http-echo.yaml#file=OutputFile_Kubernetes('http-echo.yaml')out.append(file)file.append([{'apiVersion':'apps/v1','kind':'Deployment','metadata':{'name':'echo-deployment','namespace':'default','labels':{'app':'echo'}},'spec':{'replicas':1,'selector':{'matchLabels':{'app':'echo'}},'template':{'metadata':{'labels':{'app':'echo'}},'spec':{'containers':[{'name':'echo','image':'mendhak/http-https-echo','ports':[{'containerPort':80},{'containerPort':443}],}]}}}},{'apiVersion':'v1','kind':'Service','metadata':{'name':'echo-service','namespace':'default',},'spec':{'selector':{'app':'echo'},'ports':[{'name':'http','port':80,'targetPort':80,'protocol':'TCP'}]}},{'apiVersion':'traefik.containo.us/v1alpha1','kind':'IngressRoute','metadata':{'name':'http-echo','namespace':'default',},'spec':{'entryPoints':['web'],'routes':[{# 'match': f'Host(`http-echo.localdomain`)','match':f'PathPrefix(`/`)','kind':'Rule','services':[{'name':'echo-service','port':80,}],}]}}])shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: traefik.yaml#file=OutputFile_Kubernetes('traefik.yaml')file.append(traefik_helmchart['service'].data)file.append({'apiVersion':'traefik.containo.us/v1alpha1','kind':'IngressRoute','metadata':{'name':'admin-traefik','namespace':'monitoring',},'spec':{'entryPoints':['web'],'routes':[{'match':f'Host(`admin-traefik.localdomain`)','kind':'Rule','services':[{'name':'traefik-router','port':8080,}],}]}})file.append({'apiVersion':'monitoring.coreos.com/v1','kind':'ServiceMonitor','metadata':{'name':'traefik','namespace':'monitoring','labels':{'release':'kube-prometheus-stack',},},'spec':{'selector':{'matchLabels':{'app.kubernetes.io/name':'traefik','app.kubernetes.io/instance':'traefik-router',},},'namespaceSelector':{'matchNames':['monitoring']},'endpoints':[{'port':'metrics','path':'/metrics',}],},})out.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUTFILE: ingress.yaml#file=OutputFile_Kubernetes('ingress.yaml')http_path='/'ifargs.provider!='k3d':http_path='/*'ingress_chart=Chart(data=[{'apiVersion':'extensions/v1beta1','kind':'Ingress','metadata':{'name':'ingress','namespace':'monitoring',},'spec':{'rules':[{'http':{'paths':[{'path':http_path,'backend':{'serviceName':'traefik-router','servicePort':80,}}]}}]}},])ifargs.provider=='amazon-eks':ingress_chart=ingress_chart.process(DefaultProcessor(jsonpatches=[{'condition':[{'op':'check','path':'/kind','cmp':'equals','value':'Ingress'},],'patch':[{'op':'merge','path':'/metadata','value':{'annotations':{'kubernetes.io/ingress.class':'alb','alb.ingress.kubernetes.io/scheme':'internet-facing','alb.ingress.kubernetes.io/listen-ports':'[{"HTTP": 80}]',}}}]}]))file.append(ingress_chart.data)out.append(file)shell_script.append(OD_FileTemplate(f'kubectl apply -f ${{FILE_{file.fileid}}}'))## OUTPUT#output_path=os.path.join(args.output_path,'{}-{}'.format(args.provider,datetime.datetime.today().strftime("%Y%m%d-%H%M%S")))print('Saving files to{}'.format(output_path))ifnotos.path.exists(output_path):os.makedirs(output_path)out.output(OutputDriver_Directory(output_path))if__name__=="__main__":main()Output:****** BEGIN FILE: 001-namespace.yaml ********
apiVersion: v1
kind: Namespace
metadata:
  name: monitoring

****** END FILE: 001-namespace.yaml ********
****** BEGIN FILE: 002-storage.yaml ********
apiVersion: v1
kind: PersistentVolume
metadata:
  name: prometheus-storage
  labels:
    pv.role: prometheus
spec:
  hostPath:
    path: /var/storage/prometheus
  persistentVolumeReclaimPolicy: Retain
  capacity:
    storage: 50Gi
  accessModes:
  - ReadWriteOnce

****** END FILE: 002-storage.yaml ********
****** BEGIN FILE: 003-traefik-config-crd.yaml ********
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
  name: ingressroutes.traefik.containo.us
spec:
  group: traefik.containo.us
  version: v1alpha1
  names:
    kind: IngressRoute
    plural: ingressroutes
    singular: ingressroute
  scope: Namespaced
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
<...more...>

****** END FILE: 003-traefik-config-crd.yaml ********
****** BEGIN FILE: 004-traefik-config.yaml ********
kind: ServiceAccount
apiVersion: v1
metadata:
  name: traefik-router
  labels:
    app.kubernetes.io/name: traefik
    app.kubernetes.io/instance: traefik-router
  namespace: monitoring
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: traefik-router
<...more...>
****** END FILE: 004-traefik-config.yaml ********
****** BEGIN FILE: 005-prometheus-crd.yaml ********
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.2.4
  creationTimestamp: null
  name: alertmanagerconfigs.monitoring.coreos.com
spec:
  group: monitoring.coreos.com
  names:
    kind: AlertmanagerConfig
    listKind: AlertmanagerConfigList
    plural: alertmanagerconfigs
    singular: alertmanagerconfig
  scope: Namespaced
<...more...>
****** END FILE: 005-prometheus-crd.yaml ********
****** BEGIN FILE: 006-prometheus-config.yaml ********
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: kube-prometheus-stack-grafana
  namespace: monitoring
  labels:
    app.kubernetes.io/name: grafana
    app.kubernetes.io/instance: kube-prometheus-stack
    app.kubernetes.io/version: 7.2.1
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default,runtime/default
    seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
    apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
    apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
  - FOWNER
  - FSETID
  - KILL
  - SETGID
  - SETUID
  - SETPCAP
  - NET_BIND_SERVICE
  - NET_RAW
  - SYS_CHROOT
  - MKNOD
  - AUDIT_WRITE
  - SETFCAP
<...more...>

****** END FILE: 006-prometheus-config.yaml ********
****** BEGIN FILE: 007-prometheus-job.yaml ********
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-prometheus-stack-admission-create
  namespace: monitoring
  annotations:
    helm.sh/hook: pre-install,pre-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    app: kube-prometheus-stack-admission-create
    chart: kube-prometheus-stack-12.2.3
    release: kube-prometheus-stack
spec:
  template:
    metadata:
      name: kube-prometheus-stack-admission-create
      labels:
        app: kube-prometheus-stack-admission-create
        chart: kube-prometheus-stack-12.2.3
        release: kube-prometheus-stack
        heritage: Helm
    spec:
      containers:
      - name: create
        image: jettech/kube-webhook-certgen:v1.5.0
        imagePullPolicy: IfNotPresent
        args:
        - create
        - --host=kube-prometheus-stack-operator,kube-prometheus-stack-operator.monitoring.svc
        - --namespace=monitoring
        - --secret-name=kube-prometheus-stack-admission
        resources: {}
      restartPolicy: OnFailure
      serviceAccountName: kube-prometheus-stack-admission
      securityContext:
        runAsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000
---
apiVersion: batch/v1
kind: Job
metadata:
  name: kube-prometheus-stack-admission-patch
  namespace: monitoring
  annotations:
    helm.sh/hook: post-install,post-upgrade
    helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
  labels:
    app: kube-prometheus-stack-admission-patch
    chart: kube-prometheus-stack-12.2.3
    release: kube-prometheus-stack
spec:
  template:
    metadata:
      name: kube-prometheus-stack-admission-patch
      labels:
        app: kube-prometheus-stack-admission-patch
        chart: kube-prometheus-stack-12.2.3
        release: kube-prometheus-stack
        heritage: Helm
    spec:
      containers:
      - name: patch
        image: jettech/kube-webhook-certgen:v1.5.0
        imagePullPolicy: IfNotPresent
        args:
        - patch
        - --webhook-name=kube-prometheus-stack-admission
        - --namespace=monitoring
        - --secret-name=kube-prometheus-stack-admission
        - --patch-failure-policy=Fail
        resources: {}
      restartPolicy: OnFailure
      serviceAccountName: kube-prometheus-stack-admission
      securityContext:
        runAsGroup: 2000
        runAsNonRoot: true
        runAsUser: 2000

****** END FILE: 007-prometheus-job.yaml ********
****** BEGIN FILE: 008-prometheus.yaml ********
apiVersion: v1
kind: Service
metadata:
  name: kube-prometheus-stack-grafana
  namespace: monitoring
  labels:
    app.kubernetes.io/name: grafana
    app.kubernetes.io/instance: kube-prometheus-stack
    app.kubernetes.io/version: 7.2.1
spec:
  type: ClusterIP
  ports:
  - name: service
    port: 80
    protocol: TCP
    targetPort: 3000
  selector:
    app.kubernetes.io/name: grafana
    app.kubernetes.io/instance: kube-prometheus-stack
---
apiVersion: v1
kind: Service
metadata:
  name: kube-prometheus-stack-kube-state-metrics
  namespace: monitoring
  labels:
    app.kubernetes.io/name: kube-state-metrics
    app.kubernetes.io/instance: kube-prometheus-stack
  annotations:
    prometheus.io/scrape: 'true'
spec:
  type: ClusterIP
  ports:
  - name: http
    protocol: TCP
    port: 8080
    targetPort: 8080
<...more...>
****** END FILE: 008-prometheus.yaml ********
****** BEGIN FILE: 009-http-echo.yaml ********
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo-deployment
  namespace: default
  labels:
    app: echo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: echo
  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
      - name: echo
        image: mendhak/http-https-echo
        ports:
        - containerPort: 80
        - containerPort: 443
---
apiVersion: v1
kind: Service
metadata:
  name: echo-service
  namespace: default
spec:
  selector:
    app: echo
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: http-echo
  namespace: default
spec:
  entryPoints:
  - web
  routes:
  - match: PathPrefix(`/`)
    kind: Rule
    services:
    - name: echo-service
      port: 80

****** END FILE: 009-http-echo.yaml ********
****** BEGIN FILE: 010-traefik.yaml ********
apiVersion: apps/v1
kind: Deployment
metadata:
  name: traefik-router
  labels:
    app.kubernetes.io/name: traefik
    app.kubernetes.io/instance: traefik-router
  namespace: monitoring
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: traefik
      app.kubernetes.io/instance: traefik-router
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
<...more...>

****** END FILE: 010-traefik.yaml ********
****** BEGIN FILE: 011-ingress.yaml ********
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress
  namespace: monitoring
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: traefik-router
          servicePort: 80

****** END FILE: 011-ingress.yaml ********
****** BEGIN FILE: create_k3d.sh ********
#!/bin/bash

set -e
# k3d cluster create kg2sample-prometheus-stack --port 5051:80@loadbalancer --port 5052:443@loadbalancer -v /tmp/kubragen2_samples/prometheus_stack/output/storage:/var/storage
kubectl apply -f 001-namespace.yaml
kubectl apply -f 002-storage.yaml
kubectl apply -f 003-traefik-config-crd.yaml
kubectl apply -f 004-traefik-config.yaml
kubectl apply -f 005-prometheus-crd.yaml
kubectl apply -f 006-prometheus-config.yaml
kubectl apply -f 007-prometheus-job.yaml
kubectl apply -f 008-prometheus.yaml
kubectl apply -f 009-http-echo.yaml
kubectl apply -f 010-traefik.yaml
kubectl apply -f 011-ingress.yaml

****** END FILE: create_k3d.sh ********AuthorRangel Reale (rangelreale@gmail.com)