Kubernetes рдХреНрд▓рд╕реНрдЯрд░рдордзреАрд▓ рдХрд╛рд▓рдмрд╛рд╣реНрдп рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рдХрд╛рдвреВрди рдЯрд╛рдХрдд рдЖрд╣реЗ

Kubernetes рдХреНрд▓рд╕реНрдЯрд░рдордзреАрд▓ рдХрд╛рд▓рдмрд╛рд╣реНрдп рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рдХрд╛рдвреВрди рдЯрд╛рдХрдд рдЖрд╣реЗ

рд╣рд╛рдп рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ (рдЙрд░реНрдл рдбрд┐рдкреНрд▓реЙрдп рдкреНрд░реАрд╡реНрд╣реНрдпреВ, рд░рд┐рд╡реНрд╣реНрдпреВ рдЕреЕрдк) - рд╣реЗ рддреЗрд╡реНрд╣рд╛рдЪ рд╣реЛрддреЗ рдЬреЗрд╡реНрд╣рд╛ рдХреЗрд╡рд│ рдорд╛рд╕реНрдЯрд░ рдмреНрд░рдБрдЪ рддреИрдирд╛рдд рдХреЗрд▓реА рдЬрд╛рдд рдирд╛рд╣реА, рддрд░ рдкреНрд░рддреНрдпреЗрдХ рдпреБрдирд┐рдХ URL рд╡рд░ рдкреБрд▓ рд╡рд┐рдирдВрддреА рджреЗрдЦреАрд▓ рдХреЗрд▓реА рдЬрд╛рддреЗ. рдХреЛрдб рдЙрддреНрдкрд╛рджрди рд╡рд╛рддрд╛рд╡рд░рдгрд╛рдд рдХрд╛рдо рдХрд░рддреЛ рдХреА рдирд╛рд╣реА рд╣реЗ рддреБрдореНрд╣реА рддрдкрд╛рд╕реВ рд╢рдХрддрд╛; рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рдЗрддрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХрд┐рдВрд╡рд╛ рдЙрддреНрдкрд╛рджрди рддрдЬреНрдЮрд╛рдВрдирд╛ рджрд╛рдЦрд╡рд▓реЗ рдЬрд╛рдК рд╢рдХрддреЗ. рддреБрдореНрд╣реА рдкреБрд▓ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯрдордзреНрдпреЗ рдХрд╛рдо рдХрд░рдд рдЕрд╕рддрд╛рдирд╛, рдЬреБрдиреНрдпрд╛ рдХреЛрдбрд╕рд╛рдареА рдкреНрд░рддреНрдпреЗрдХ рдирд╡реАрди рдХрдорд┐рдЯ рд╡рд░реНрддрдорд╛рди рдбрд┐рдкреНрд▓реЙрдп рд╣рдЯрд╡рд▓рд╛ рдЬрд╛рддреЛ рдЖрдгрд┐ рдирд╡реАрди рдХреЛрдбрд╕рд╛рдареА рдирд╡реАрди рдбрд┐рдкреНрд▓реЙрдп рд░реЛрд▓ рдЖрдЙрдЯ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ. рдЬреЗрд╡реНрд╣рд╛ рддреБрдореНрд╣реА рдорд╛рд╕реНрдЯрд░ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдкреБрд▓ рд╡рд┐рдирдВрддреА рд╡рд┐рд▓реАрди рдХрд░рддрд╛ рддреЗрд╡реНрд╣рд╛ рдкреНрд░рд╢реНрди рдЙрджреНрднрд╡реВ рд╢рдХрддрд╛рдд. рддреБрдореНрд╣рд╛рд▓рд╛ рдпрд╛рдкреБрдвреЗ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦреЗрдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╛рд╣реА, рдкрд░рдВрддреБ Kubernetes рд╕рдВрд╕рд╛рдзрдиреЗ рдЕрдЬреВрдирд╣реА рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдЖрд╣реЗрдд.

рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛рдВрдмрджреНрджрд▓ рдЕрдзрд┐рдХ

рдХреБрдмрд░реНрдиреЗрдЯреНрд╕рдордзреНрдпреЗ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рдмрдирд╡рдгреНрдпрд╛рдЪрд╛ рдПрдХ рджреГрд╖реНрдЯреАрдХреЛрди рдореНрд╣рдгрдЬреЗ рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕ рд╡рд╛рдкрд░рдгреЗ. рдереЛрдбрдХреНрдпрд╛рдд, рдЙрддреНрдкрд╛рджрди рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЕрд╕реЗ рджрд┐рд╕рддреЗ:

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end
spec:
  replicas: 3
...

рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦреЗрд╕рд╛рдареА, рдПрдХ рдиреЗрдорд╕реНрдкреЗрд╕ рддреНрдпрд╛рдЪреНрдпрд╛ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░рд╕рд╣ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдкреБрд▓ рд╡рд┐рдирдВрддреА рдХреНрд░рдорд╛рдВрдХ) рдЖрдгрд┐ рдХрд╛рд╣реА рдкреНрд░рдХрд╛рд░рдЪреЗ рдЙрдкрд╕рд░реНрдЧ/рдкреЛрд╕реНрдЯрдлрд┐рдХреНрд╕ рддрдпрд╛рд░ рдХреЗрд▓реЗ рдЬрд╛рддреЗ (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, -pr-):

kind: Namespace
apiVersion: v1
metadata:
  name: habr-back-end-pr-17
...

kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: habr-back-end-pr-17
spec:
  replicas: 1
...

рд╕рд░реНрд╡рд╕рд╛рдзрд╛рд░рдгрдкрдгреЗ, рдореА рд▓рд┐рд╣рд┐рд▓реЗ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдСрдкрд░реЗрдЯрд░ (рдХреНрд▓рд╕реНрдЯрд░ рд╕рдВрд╕рд╛рдзрдирд╛рдВрдордзреНрдпреЗ рдкреНрд░рд╡реЗрд╢ рдЕрд╕рд▓реЗрд▓рд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ), Github рд╡рд░ рдкреНрд░рдХрд▓реНрдкрд╛рдЪрд╛ рджреБрд╡рд╛. рд╣реЗ рдЬреБрдиреНрдпрд╛ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛рдВрд╢реА рд╕рдВрдмрдВрдзрд┐рдд рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕ рдХрд╛рдвреВрди рдЯрд╛рдХрддреЗ. Kubernetes рдордзреНрдпреЗ, рддреБрдореНрд╣реА рдиреЗрдорд╕реНрдкреЗрд╕ рд╣рдЯрд╡рд▓реНрдпрд╛рд╕, рддреНрдпрд╛ рдиреЗрдорд╕реНрдкреЗрд╕рдордзреАрд▓ рдЗрддрд░ рд╕рдВрд╕рд╛рдзрдиреЗ рджреЗрдЦреАрд▓ рдЖрдкреЛрдЖрдк рд╣рдЯрд╡рд▓реА рдЬрд╛рддрд╛рдд.

$ kubectl get pods --all-namespaces | grep -e "-pr-"
NAMESPACE            ... AGE
habr-back-end-pr-264 ... 4d8h
habr-back-end-pr-265 ... 5d7h

рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рдХрд╢рд╛ рд▓рд╛рдЧреВ рдХрд░рд╛рдпрдЪреНрдпрд╛ рдпрд╛рдмрджреНрджрд▓ рддреБрдореНрд╣реА рд╡рд╛рдЪреВ рд╢рдХрддрд╛ рдпреЗрдереЗ ╨╕ рдпреЗрдереЗ.

рдкреНрд░реЗрд░рдгрд╛

рд╕рддрдд рдПрдХрддреНрд░реАрдХрд░рдгрд╛рд╕рд╣ рдард░рд╛рд╡рд┐рдХ рдкреБрд▓ рд╡рд┐рдирдВрддреА рдЬреАрд╡рдирдЪрдХреНрд░ рдкрд╛рд╣реВрдпрд╛ (continuous integration):

  1. рдЖрдореНрд╣реА рд╢рд╛рдЦреЗрдд рдПрдХ рдирд╡реАрди рд╡рдЪрдирдмрджреНрдзрддрд╛ рдврдХрд▓рддреЛ.
  2. рдмрд┐рд▓реНрдбрд╡рд░, рд▓рд┐рдВрдЯрд░ рдЖрдгрд┐/рдХрд┐рдВрд╡рд╛ рдЪрд╛рдЪрдгреНрдпрд╛ рдЪрд╛рд▓рд╡рд▓реНрдпрд╛ рдЬрд╛рддрд╛рдд.
  3. рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдкреБрд▓ рд╡рд┐рдирдВрддреА рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдлреНрд▓рд╛рдпрд╡рд░ рд╡реНрдпреБрддреНрдкрдиреНрди рдХреЗрд▓реЗ рдЬрд╛рддрд╛рдд (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рддреНрдпрд╛рдЪрд╛ рдирдВрдмрд░ рддрдпрд╛рд░ рдЯреЗрдореНрдкрд▓реЗрдЯрдордзреНрдпреЗ рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ).
  4. kubectl рд▓рд╛рдЧреВ рд╡рд╛рдкрд░реВрди, рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЬреЛрдбрд▓реЗ рдЬрд╛рддрд╛рдд (рдЙрдкрдпреЛрдЬрди).
  5. рдкреБрд▓ рд╡рд┐рдирдВрддреА рдорд╛рд╕реНрдЯрд░ рд╢рд╛рдЦреЗрдд рд╡рд┐рд▓реАрди рдХреЗрд▓реА рдЖрд╣реЗ.

рддреБрдореНрд╣реА рдкреБрд▓ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯрдордзреНрдпреЗ рдХрд╛рдо рдХрд░рдд рдЕрд╕рддрд╛рдирд╛, рдЬреБрдиреНрдпрд╛ рдХреЛрдбрд╕рд╛рдареА рдкреНрд░рддреНрдпреЗрдХ рдирд╡реАрди рдХрдорд┐рдЯ рд╡рд░реНрддрдорд╛рди рдбрд┐рдкреНрд▓реЙрдп рд╣рдЯрд╡рд▓рд╛ рдЬрд╛рддреЛ рдЖрдгрд┐ рдирд╡реАрди рдХреЛрдбрд╕рд╛рдареА рдирд╡реАрди рдбрд┐рдкреНрд▓реЙрдп рд░реЛрд▓ рдЖрдЙрдЯ рдХреЗрд▓рд╛ рдЬрд╛рддреЛ. рдкрд░рдВрддреБ рдЬреЗрд╡реНрд╣рд╛ рдкреБрд▓ рд╡рд┐рдирдВрддреА рдорд╛рд╕реНрдЯрд░ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рд╡рд┐рд▓реАрди рдХреЗрд▓реА рдЬрд╛рддреЗ, рддреЗрд╡реНрд╣рд╛ рдлрдХреНрдд рдорд╛рд╕реНрдЯрд░ рдмреНрд░рд╛рдВрдЪ рдмрд╛рдВрдзрд▓реА рдЬрд╛рдИрд▓. рдкрд░рд┐рдгрд╛рдореА, рдЕрд╕реЗ рджрд┐рд╕реВрди рдЖрд▓реЗ рдХреА рдЖрдореНрд╣реА рдкреБрд▓ рд╡рд┐рдирдВрддреАрдмрджреНрджрд▓ рдЖрдзреАрдЪ рд╡рд┐рд╕рд░рд▓реЛ рдЖрд╣реЛрдд рдЖрдгрд┐ рддреНрдпрд╛рдЪреЗ рдХреБрдмрд░рдиреЗрдЯ рд╕рдВрд╕рд╛рдзрдиреЗ рдЕрджреНрдпрд╛рдк рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдЖрд╣реЗрдд.

рдХрд╕реЗ рд╡рд╛рдкрд░рд╛рд╡реЗ

рдЦрд╛рд▓реАрд▓ рдЖрджреЗрд╢рд╛рд╕рд╣ рдкреНрд░рдХрд▓реНрдк рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml

рдЦрд╛рд▓реАрд▓ рд╕рд╛рдордЧреНрд░реАрд╕рд╣ рдлрд╛рдЗрд▓ рддрдпрд╛рд░ рдХрд░рд╛ рдЖрдгрд┐ рджреНрд╡рд╛рд░реЗ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛ kubectl apply -f:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 3

рдкреЕрд░рд╛рдореАрдЯрд░ namespaceSubstring рдЗрддрд░ рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕рдордзреВрди рдкреБрд▓ рд╡рд┐рдирдВрддреНрдпрд╛рдВрд╕рд╛рдареА рдиреЗрдорд╕реНрдкреЗрд╕ рдлрд┐рд▓реНрдЯрд░ рдХрд░рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдЦрд╛рд▓реАрд▓ рдиреЗрдорд╕реНрдкреЗрд╕ рдЕрд╕рд▓реНрдпрд╛рд╕: habr-back-end, habr-front-end, habr-back-end-pr-17, habr-back-end-pr-33, рдирдВрддрд░ рд╣рдЯрд╡рд┐рдгреНрдпрд╛рдЪреЗ рдЙрдореЗрджрд╡рд╛рд░ рдЕрд╕рддреАрд▓ habr-back-end-pr-17, habr-back-end-pr-33.

рдкреЕрд░рд╛рдореАрдЯрд░ afterDaysWithoutDeploy рдЬреБрдиреА рдиреЗрдорд╕реНрдкреЗрд╕ рд╣рдЯрд╡рдгреНрдпрд╛рд╕рд╛рдареА рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдиреЗрдорд╕реНрдкреЗрд╕ рддрдпрд╛рд░ рдХреЗрд▓реНрдпрд╛рд╕ 3 ╨┤╨╜╤П 1 ╤З╨░╤Б рдорд╛рдЧреЗ, рдЖрдгрд┐ рдкреЕрд░рд╛рдореАрдЯрд░ рд╕реВрдЪрд┐рдд рдХрд░рддреЗ 3 ╨┤╨╜╤П, рд╣реЗ рдиреЗрдорд╕реНрдкреЗрд╕ рд╣рдЯрд╡рд▓реЗ рдЬрд╛рдИрд▓. рдиреЗрдорд╕реНрдкреЗрд╕ рддрдпрд╛рд░ рдХреЗрд▓реНрдпрд╛рд╕ рддреЗ рд╡рд┐рд░реБрджреНрдз рджрд┐рд╢реЗрдиреЗ рджреЗрдЦреАрд▓ рдХрд╛рд░реНрдп рдХрд░рддреЗ 2 ╨┤╨╜╤П 23 ╤З╨░╤Б╨░ рдорд╛рдЧреЗ, рдЖрдгрд┐ рдкреЕрд░рд╛рдореАрдЯрд░ рд╕реВрдЪрд┐рдд рдХрд░рддреЗ 3 ╨┤╨╜╤П, рд╣реЗ рдиреЗрдорд╕реНрдкреЗрд╕ рд╣рдЯрд╡рд▓реЗ рдЬрд╛рдгрд╛рд░ рдирд╛рд╣реА.

рдЖрдгрдЦреА рдПрдХ рдкреЕрд░рд╛рдореАрдЯрд░ рдЖрд╣реЗ, рд╕рд░реНрд╡ рдиреЗрдорд╕реНрдкреЗрд╕ рдХрд┐рддреА рд╡реЗрд│рд╛ рд╕реНрдХреЕрди рдХрд░рд╛рдпрдЪреЗ рдЖрдгрд┐ рдЙрдкрдпреЛрдЬрдирд╛рд╢рд┐рд╡рд╛рдп рджрд┐рд╡рд╕ рддрдкрд╛рд╕рд╛рдпрдЪреЗ рдпрд╛рд╕рд╛рдареА рддреЗ рдЬрдмрд╛рдмрджрд╛рд░ рдЖрд╣реЗ - рдкреНрд░рддреНрдпреЗрдХ рдорд┐рдирд┐рдЯ рддрдкрд╛рд╕рд╛. рдбреАрдлреЙрд▓реНрдЯрдиреБрд╕рд╛рд░ рддреЗ рд╕рдорд╛рди рдЖрд╣реЗ 30 ╨╝╨╕╨╜╤Г╤В╨░╨╝.

рдпрд╛ рдХрд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ

рд╕рд░рд╛рд╡ рдордзреНрдпреЗ, рдЖрдкрд▓реНрдпрд╛рд▓рд╛ рдпрд╛рдЪреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╕реЗрд▓:

  1. рдЧреЛрджреА рдХрд╛рдордЧрд╛рд░ рд╡реЗрдЧрд│реНрдпрд╛ рд╡рд╛рддрд╛рд╡рд░рдгрд╛рдд рдХрд╛рдо рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА.
  2. рдорд┐рдиреАрдХреБрдмреЗ рд╕реНрдерд╛рдирд┐рдХ рдкрд╛рддрд│реАрд╡рд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдХреНрд▓рд╕реНрдЯрд░ рд╡рд╛рдврд╡реЗрд▓.
  3. kubectl - рдХреНрд▓рд╕реНрдЯрд░ рд╡реНрдпрд╡рд╕реНрдерд╛рдкрдирд╛рд╕рд╛рдареА рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЗрдВрдЯрд░рдлреЗрд╕.

рдЖрдореНрд╣реА рд╕реНрдерд╛рдирд┐рдХ рдкрд╛рддрд│реАрд╡рд░ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдХреНрд▓рд╕реНрдЯрд░ рд╡рд╛рдврд╡рддреЛ:

$ minikube start --vm-driver=docker
minikube v1.11.0 on Darwin 10.15.5
Using the docker driver based on existing profile.
Starting control plane node minikube in cluster minikube.

рд╕реВрдЪрд┐рдд рдХрд░рд╛ kubectl рдбреАрдлреЙрд▓реНрдЯрдиреБрд╕рд╛рд░ рд╕реНрдерд╛рдирд┐рдХ рдХреНрд▓рд╕реНрдЯрд░ рд╡рд╛рдкрд░рд╛:

$ kubectl config use-context minikube
Switched to context "minikube".

рдЙрддреНрдкрд╛рджрди рд╡рд╛рддрд╛рд╡рд░рдгрд╛рд╕рд╛рдареА рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рд╛:

$ curl https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/configs/production.yml > stale-feature-branch-production-configs.yml

рдкреНрд░реЛрдбрдХреНрд╢рди рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рдЬреБрдиреА рдиреЗрдорд╕реНрдкреЗрд╕ рддрдкрд╛рд╕рдгреНрдпрд╛рд╕рд╛рдареА рдХреЙрдиреНрдлрд┐рдЧрд░ рдХреЗрд▓реЗрд▓реА рдЕрд╕рд▓реНрдпрд╛рдиреЗ рдЖрдгрд┐ рдЖрдордЪреНрдпрд╛ рдирд╡реНрдпрд╛рдиреЗ рдЙрднрд╛рд░рд▓реЗрд▓реНрдпрд╛ рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рддреЗ рдирд╕рд▓реНрдпрд╛рдореБрд│реЗ, рдЖрдореНрд╣реА рдкрд░реНрдпрд╛рд╡рд░рдг рд╡реНрд╣реЗрд░рд┐рдПрдмрд▓ рдмрджрд▓реВ. IS_DEBUG рд╡рд░ true. рдпрд╛ рдореВрд▓реНрдпрд╛рд╕рд╣ рдкреЕрд░рд╛рдореАрдЯрд░ afterDaysWithoutDeploy рдЦрд╛рддреНрдпрд╛рдд рдШреЗрддрд▓реЗ рдЬрд╛рдд рдирд╛рд╣реА рдЖрдгрд┐ рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕ рдЙрдкрдпреЛрдЬрд┐рдд рдХреЗрд▓реНрдпрд╛рд╢рд┐рд╡рд╛рдп рджрд┐рд╡рд╕ рддрдкрд╛рд╕рд▓реНрдпрд╛ рдЬрд╛рдд рдирд╛рд╣реАрдд, рдлрдХреНрдд рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧрдЪреНрдпрд╛ рдШрдЯрдиреЗрд╕рд╛рдареА (-pr-).

рдЖрдкрдг рдЪрд╛рд▓реВ рдЕрд╕рд▓реНрдпрд╛рд╕ Linux:

$ sed -i 's|false|true|g' stale-feature-branch-production-configs.yml

рдЖрдкрдг рдЪрд╛рд▓реВ рдЕрд╕рд▓реНрдпрд╛рд╕ macOS:

$ sed -i "" 's|false|true|g' stale-feature-branch-production-configs.yml

рдкреНрд░рдХрд▓реНрдк рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдд рдЖрд╣реЗ:

$ kubectl apply -f stale-feature-branch-production-configs.yml

рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рд╕рдВрд╕рд╛рдзрди рджрд┐рд╕рд▓реЗ рдЖрд╣реЗ рд╣реЗ рддрдкрд╛рд╕рдд рдЖрд╣реЗ StaleFeatureBranch:

$ kubectl api-resources | grep stalefeaturebranches
NAME                 ... APIGROUP                             ... KIND
stalefeaturebranches ... feature-branch.dmytrostriletskyi.com ... StaleFeatureBranch

рдЖрдореНрд╣реА рддрдкрд╛рд╕рддреЛ рдХреА рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдСрдкрд░реЗрдЯрд░ рджрд┐рд╕рд▓рд╛ рдЖрд╣реЗ:

$ kubectl get pods --namespace stale-feature-branch-operator
NAME                                           ... STATUS  ... AGE
stale-feature-branch-operator-6bfbfd4df8-m7sch ... Running ... 38s

рдЖрдкрдг рддреНрдпрд╛рдЪреЗ рд▓реЙрдЧ рдкрд╛рд╣рд┐рд▓реНрдпрд╛рд╕, рддреЗ рд╕рдВрд╕рд╛рдзрдирд╛рдВрд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рддрдпрд╛рд░ рдЖрд╣реЗ StaleFeatureBranch:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Operator Version: 0.0.1"}
...
... "msg":"Starting EventSource", ... , "source":"kind source: /, Kind="}
... "msg":"Starting Controller", ...}
... "msg":"Starting workers", ..., "worker count":1}

рдЖрдореНрд╣реА рд░реЗрдбреАрдореЗрдб рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЛ fixtures (рдХреНрд▓рд╕реНрдЯрд░ рд╕рдВрд╕рд╛рдзрдирд╛рдВрдЪреНрдпрд╛ рдореЙрдбреЗрд▓рд┐рдВрдЧрд╕рд╛рдареА рддрдпрд╛рд░ рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди) рд╕рдВрд╕рд╛рдзрдирд╛рд╕рд╛рдареА StaleFeatureBranch:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/stale-feature-branch.yml

рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рд╕рдмрд╕реНрдЯреНрд░рд┐рдВрдЧрд╕рд╣ рдиреЗрдорд╕реНрдкреЗрд╕ рд╢реЛрдзрдгреНрдпрд╛рд╕рд╛рдареА рд╕реВрдЪрд┐рдд рдХрд░рддрд╛рдд -pr- рдПрдХрджрд╛ рдордзреНрдпреЗ 1 ╨╝╨╕╨╜╤Г╤В╤Г.:

apiVersion: feature-branch.dmytrostriletskyi.com/v1
kind: StaleFeatureBranch
metadata:
  name: stale-feature-branch
spec:
  namespaceSubstring: -pr-
  afterDaysWithoutDeploy: 1 
  checkEveryMinutes: 1

рдСрдкрд░реЗрдЯрд░рдиреЗ рдкреНрд░рддрд┐рд╕рд╛рдж рджрд┐рд▓рд╛ рдЖрд╣реЗ рдЖрдгрд┐ рдиреЗрдорд╕реНрдкреЗрд╕ рддрдкрд╛рд╕рдгреНрдпрд╛рд╕рд╛рдареА рддрдпрд╛рд░ рдЖрд╣реЗ:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Stale feature branch is being processing.","namespaceSubstring":"-pr-","afterDaysWithoutDeploy":1,"checkEveryMinutes":1,"isDebug":"true"}

рд╕реНрдерд╛рдкрд┐рдд рдХрд░рд╛ fixtures, рджреЛрди рдиреЗрдорд╕реНрдкреЗрд╕ рдЕрд╕рд▓реЗрд▓реЗ (project-pr-1, project-pr-2) рдЖрдгрд┐ рддреЗ deployments, services, ingress, рдЖрдгрд┐ рдЕрд╕реЗрдЪ:

$ kubectl apply -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/first-feature-branch.yml -f https://raw.githubusercontent.com/dmytrostriletskyi/stale-feature-branch-operator/master/fixtures/second-feature-branch.yml
...
namespace/project-pr-1 created
deployment.apps/project-pr-1 created
service/project-pr-1 created
horizontalpodautoscaler.autoscaling/project-pr-1 created
secret/project-pr-1 created
configmap/project-pr-1 created
ingress.extensions/project-pr-1 created
namespace/project-pr-2 created
deployment.apps/project-pr-2 created
service/project-pr-2 created
horizontalpodautoscaler.autoscaling/project-pr-2 created
secret/project-pr-2 created
configmap/project-pr-2 created
ingress.extensions/project-pr-2 created

рдЖрдореНрд╣реА рддрдкрд╛рд╕рддреЛ рдХреА рд╡рд░реАрд▓ рд╕рд░реНрд╡ рд╕рдВрд╕рд╛рдзрдиреЗ рдпрд╢рд╕реНрд╡реАрд░рд┐рддреНрдпрд╛ рддрдпрд╛рд░ рдХреЗрд▓реА рдЧреЗрд▓реА рдЖрд╣реЗрдд:

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...
NAME                              ... READY ... STATUS  ... AGE
pod/project-pr-1-848d5fdff6-rpmzw ... 1/1   ... Running ... 67s

NAME                         ... READY ... AVAILABLE ... AGE
deployment.apps/project-pr-1 ... 1/1   ... 1         ... 67s
...

рдЖрдореНрд╣реА рд╕рдорд╛рд╡рд┐рд╖реНрдЯ рдХреЗрд▓реНрдпрд╛рдкрд╛рд╕реВрди debug, рдиреЗрдорд╕реНрдкреЗрд╕реЗрд╕ project-pr-1 ╨╕ project-pr-2, рдореНрд╣рдгреВрди рдкреЕрд░рд╛рдореАрдЯрд░ рд╡рд┐рдЪрд╛рд░рд╛рдд рди рдШреЗрддрд╛ рдЗрддрд░ рд╕рд░реНрд╡ рд╕рдВрд╕рд╛рдзрдиреЗ рддреНрд╡рд░рд┐рдд рд╣рдЯрд╡рд╛рд╡реА рд▓рд╛рдЧрддреАрд▓ afterDaysWithoutDeploy. рд╣реЗ рдСрдкрд░реЗрдЯрд░ рд▓реЙрдЧрдордзреНрдпреЗ рдкрд╛рд╣рд┐рд▓реЗ рдЬрд╛рдК рд╢рдХрддреЗ:

$ kubectl logs stale-feature-branch-operator-6bfbfd4df8-m7sch -n stale-feature-branch-operator
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-1"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-1","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-1"}
... "msg":"Namespace should be deleted due to debug mode is enabled.","namespaceName":"project-pr-2"}
... "msg":"Namespace is being processing.","namespaceName":"project-pr-2","namespaceCreationTimestamp":"2020-06-16 18:43:58 +0300 EEST"}
... "msg":"Namespace has been deleted.","namespaceName":"project-pr-2"}

рдЖрдкрдг рд╕рдВрд╕рд╛рдзрдирд╛рдВрдЪреА рдЙрдкрд▓рдмреНрдзрддрд╛ рддрдкрд╛рд╕рд▓реНрдпрд╛рд╕, рддреЗ рд╕реНрдерд┐рддреАрдд рдЕрд╕рддреАрд▓ Terminating (рд╣рдЯрд╡рд┐рдгреНрдпрд╛рдЪреА рдкреНрд░рдХреНрд░рд┐рдпрд╛) рдХрд┐рдВрд╡рд╛ рдЖрдзреАрдЪ рд╣рдЯрд╡рд┐рд▓реЗрд▓реЗ (рдХрдорд╛рдВрдб рдЖрдЙрдЯрдкреБрдЯ рд░рд┐рдХреНрдд рдЖрд╣реЗ).

$ kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-1 && kubectl get namespace,pods,deployment,service,horizontalpodautoscaler,configmap,ingress -n project-pr-2
...

рдЖрдкрдг рдирд┐рд░реНрдорд┐рддреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдкреБрдиреНрд╣рд╛ рдХрд░реВ рд╢рдХрддрд╛ fixtures рдЕрдиреЗрдХ рд╡реЗрд│рд╛ рдЖрдгрд┐ рддреЗ рдПрдХрд╛ рдорд┐рдирд┐рдЯрд╛рдд рдХрд╛рдврд▓реЗ рдЬрд╛рддреАрд▓ рдпрд╛рдЪреА рдЦрд╛рддреНрд░реА рдХрд░рд╛.

рд╡рд┐рдХрд▓реНрдк

рдХреНрд▓рд╕реНрдЯрд░рдордзреНрдпреЗ рдХрд╛рдо рдХрд░рдгрд╛рд▒реНрдпрд╛ рдСрдкрд░реЗрдЯрд░рдРрд╡рдЬреА рдХрд╛рдп рдХрд░рддрд╛ рдпреЗрдИрд▓? рддреЗрдереЗ рдЕрдиреЗрдХ рджреГрд╖реНрдЯрд┐рдХреЛрди рдЖрд╣реЗрдд, рддреЗ рд╕рд░реНрд╡ рдЕрдкреВрд░реНрдг рдЖрд╣реЗрдд (рдЖрдгрд┐ рддреНрдпрд╛рдВрдЪреНрдпрд╛ рдЙрдгреАрд╡рд╛ рд╡реНрдпрдХреНрддрд┐рдирд┐рд╖реНрда рдЖрд╣реЗрдд), рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХрдЬрдг рд╕реНрд╡рдд: рд╕рд╛рдареА рдард░рд╡рддреЛ рдХреА рдПрдЦрд╛рджреНрдпрд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд▓реНрдкрд╛рд╕рд╛рдареА рдХрд╛рдп рд╕рд░реНрд╡реЛрддреНрддрдо рдЖрд╣реЗ:

  1. рдорд╛рд╕реНрдЯрд░ рд╢рд╛рдЦреЗрдЪреНрдпрд╛ рд╕рддрдд рдПрдХрддреНрд░реАрдХрд░рдгрд╛рджрд░рдореНрдпрд╛рди рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рд╣рдЯрд╡рд╛.

    • рд╣реЗ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА, рддреБрдореНрд╣рд╛рд▓рд╛ рдХреЛрдгрддреА рдкреБрд▓ рд╡рд┐рдирдВрддреА рдмрд╛рдВрдзрд▓реА рдЬрд╛рдд рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдХрдорд┐рдЯрд╢реА рд╕рдВрдмрдВрдзрд┐рдд рдЖрд╣реЗ рд╣реЗ рдорд╛рд╣рд┐рдд рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ. рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦреЗрдЪреНрдпрд╛ рдиреЗрдорд╕реНрдкреЗрд╕рдордзреНрдпреЗ рдкреБрд▓ рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рдЖрдпрдбреЗрдВрдЯрд┐рдлрд╛рдпрд░ - рддреНрдпрд╛рдЪрд╛ рдХреНрд░рдорд╛рдВрдХ рдХрд┐рдВрд╡рд╛ рд╢рд╛рдЦреЗрдЪреЗ рдирд╛рд╡ рдЕрд╕рд▓реНрдпрд╛рдиреЗ, рдЕрднрд┐рдЬреНрдЮрд╛рдкрдХ рдиреЗрд╣рдореА рдХрдорд┐рдЯрдордзреНрдпреЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рд╛рд╡рд╛ рд▓рд╛рдЧреЗрд▓.
    • рдореБрдЦреНрдп рд╢рд╛рдЦрд╛ рдмрд┐рд▓реНрдб рдЕрдпрд╢рд╕реНрд╡реА рд╣реЛрдд рдЖрд╣реЗрдд. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рддреБрдордЪреНрдпрд╛рдХрдбреЗ рдЦрд╛рд▓реАрд▓ рдЯрдкреНрдкреЗ рдЖрд╣реЗрдд: рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рд╛, рдЪрд╛рдЪрдгреНрдпрд╛ рдЪрд╛рд▓рд╡рд╛, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рддрдпрд╛рд░ рдХрд░рд╛, рд░рд┐рд▓реАрдЭ рдХрд░рд╛, рд╕реВрдЪрдирд╛ рдкрд╛рдард╡рд╛, рд╢реЗрд╡рдЯрдЪреНрдпрд╛ рдкреБрд▓ рд╡рд┐рдирдВрддреАрдЪреА рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рд╕рд╛рдл рдХрд░рд╛. рд╕реВрдЪрдирд╛ рдкрд╛рдард╡рддрд╛рдирд╛ рдмрд┐рд▓реНрдб рдЕрдпрд╢рд╕реНрд╡реА рдЭрд╛рд▓реНрдпрд╛рд╕, рддреБрдореНрд╣рд╛рд▓рд╛ рдХреНрд▓рд╕реНрдЯрд░рдордзреАрд▓ рд╕рд░реНрд╡ рд╕рдВрд╕рд╛рдзрдиреЗ рд╡реНрдпрдХреНрддрд┐рдЪрд▓рд┐рддрдкрдгреЗ рд╣рдЯрд╡рд╛рд╡реА рд▓рд╛рдЧрддреАрд▓.
    • рдпреЛрдЧреНрдп рд╕рдВрджрд░реНрднрд╛рд╢рд┐рд╡рд╛рдп, рдорд╛рд╕реНрдЯрд░ рдмрд┐рд▓реНрдбрдордзреАрд▓ рд╡реИрд╢рд┐рд╖реНрдЯреНрдп рд╢рд╛рдЦрд╛ рд╣рдЯрд╡рдгреЗ рд╕реНрдкрд╖реНрдЯ рдирд╛рд╣реА.

  2. рд╡реЗрдмрд╣реБрдХ рд╡рд╛рдкрд░рдгреЗ (рдЙрджрд╛рд╣рд░рдг).

    • рд╣рд╛ рддреБрдордЪрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрди рдЕрд╕реВ рд╢рдХрдд рдирд╛рд╣реА. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдордзреНрдпреЗ рдЬреЗрдирдХрд┐рдиреНрд╕, рдлрдХреНрдд рдПрдХ рдкреНрд░рдХрд╛рд░рдЪреА рдкрд╛рдЗрдкрд▓рд╛рдЗрди рддреНрдпрд╛рдЪреА рдХреЙрдиреНрдлрд┐рдЧрд░реЗрд╢рди рд╕реНрддреНрд░реЛрдд рдХреЛрдбрдордзреНрдпреЗ рдЬрддрди рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рдХреНрд╖рдорддреЗрд╕ рд╕рдорд░реНрдерди рджреЗрддреЗ. рд╡реЗрдмрд╣реБрдХ рд╡рд╛рдкрд░рддрд╛рдирд╛, рддреНрдпрд╛рд╡рд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА рддреБрдореНрд╣рд╛рд▓рд╛ рддреБрдордЪреА рд╕реНрд╡рддрдГрдЪреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓рд┐рд╣рд╛рд╡реА рд▓рд╛рдЧреЗрд▓. рд╣реА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЬреЗрдирдХрд┐рдиреНрд╕ рдЗрдВрдЯрд░рдлреЗрд╕рдордзреНрдпреЗ рдареЗрд╡рд╛рд╡реА рд▓рд╛рдЧреЗрд▓, рдЬреА рд░рд╛рдЦрдгреЗ рдХрдареАрдг рдЖрд╣реЗ.

  3. рд▓рд┐рд╣рд╛рдпрд▓рд╛ рдХреНрд░реЛрдирдЬреЙрдм рдЖрдгрд┐ рдХреБрдмрд░реНрдиреЗрдЯреНрд╕ рдХреНрд▓рд╕реНрдЯрд░ рдЬреЛрдбрд╛.

    • рд▓реЗрдЦрди рдЖрдгрд┐ рд╕рдорд░реНрдердирд╛рд╕рд╛рдареА рд╡реЗрд│ рдШрд╛рд▓рд╡рдгреЗ.
    • рдСрдкрд░реЗрдЯрд░ рдЖрдзреАрдкрд╛рд╕реВрдирдЪ рд╕рдорд╛рди рд╢реИрд▓реАрдордзреНрдпреЗ рдХрд╛рд░реНрдп рдХрд░рддреЛ, рджрд╕реНрддрдРрд╡рдЬреАрдХрд░рдг рдЖрдгрд┐ рд╕рдорд░реНрдерд┐рдд рдЖрд╣реЗ.

рд▓реЗрдЦрд╛рдХрдбреЗ рд▓рдХреНрд╖ рджрд┐рд▓реНрдпрд╛рдмрджреНрджрд▓ рдзрдиреНрдпрд╡рд╛рдж. Github рд╡рд░ рдкреНрд░рдХрд▓реНрдкрд╛рдЪрд╛ рджреБрд╡рд╛.

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛