αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αž™αžΎαž„αž“αžΉαž„αž”αŸ’αžšαžΎ Gitlab CI αž“αž·αž„ GitOps αžŠαŸ„αž™αžŠαŸƒ αžŠαžΎαž˜αŸ’αž”αžΈαž’αž“αž»αžœαžαŸ’αž αž“αž·αž„αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αž’αžαŸ’αžαž”αž‘αž–αžΈαžŸαŸŠαŸαžšαžΈαž“αŸαŸ‡αŸ–

αž™αžΎαž„αž“αžΉαž„αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αžŠαŸ„αž™αžŠαŸƒαžαžΆαž˜αžšαž™αŸˆ GitOps αž“αž·αž„αž”αž„αŸ’αž€αžΎαž/αž€αŸ‚αž”αŸ’αžšαŸ‚αž’αž“αž’αžΆαž“ Kubernetes αžŸαŸ†αžαžΆαž“αŸ‹αŸ—αŸ” αž’αžαŸ’αžαž”αž‘αž“αŸαŸ‡αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž˜αŸ’αžšαž»αž„αž‘αž»αž€αž‡αžΆαž…αž˜αŸ’αž”αž„αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžŽαŸ‚αž“αžΆαŸ† αž‡αžΆαž˜αž½αž™αž“αžΉαž„αžšαž”αŸ€αž”αžŠαŸ‚αž›αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes Canary αž…αžΆαž”αŸ‹αžαžΆαŸ†αž„αž–αžΈαž˜αžΆαž“αžœαž·αž’αžΈαžŸαžΆαžŸαŸ’αžšαŸ’αžαžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž€αž˜αŸ’αž˜αžŠαŸ‚αž›αž˜αžΆαž“αž”αŸ’αžšαžŸαž·αž‘αŸ’αž’αž—αžΆαž–αž‡αžΆαž„αž˜αž»αž“ αžŠαŸ‚αž›αž™αžΎαž„αž“αžΉαž„αž–αž·αž…αžΆαžšαžŽαžΆαž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸ”


αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

https://www.norberteder.com/canary-deployment/

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary

αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž™αž»αž‘αŸ’αž’αžŸαžΆαžŸαŸ’αžαŸ’αžš Canary αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžαŸ’αžšαžΌαžœαž”αžΆαž“αž’αž“αž»αžœαžαŸ’αžαžŠαŸ†αž”αžΌαž„αž…αŸ†αž–αŸ„αŸ‡αžαŸ‚αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž˜αž½αž™αž…αŸ†αž“αž½αž“αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ” αžαžΆαž˜αžšαž™αŸˆαž€αžΆαžšαžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™ αž‘αž·αž“αŸ’αž“αž“αŸαž™αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» αž€αžΆαžšαž’αŸ’αžœαžΎαžαŸαžŸαŸ’αžαžŠαŸ„αž™αžŠαŸƒ αž¬αž”αžŽαŸ’αžαžΆαž‰αž˜αžαž·αž€αŸ‚αž›αž˜αŸ’αž’αž•αŸ’αžŸαŸαž„αž‘αŸ€αž αž€αžΆαžšαž…αŸαž‰αž•αŸ’αžŸαžΆαž™αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαžΆαž€αž›αŸ’αž”αž„ αž˜αž»αž“αž–αŸαž›αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αŸαž‰αž•αŸ’αžŸαžΆαž™αž‘αŸ…αž€αžΆαž“αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ”

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Kubernetes (αž€αžΆαžšαž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αžšαŸ†αž€αž·αž›)

αž™αž»αž‘αŸ’αž’αžŸαžΆαžŸαŸ’αžαŸ’αžšαž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžŠαžΆαž€αŸ‹αž±αŸ’αž™αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Kubernetes αž‚αžΊαž€αžΆαžšαž’αžΆαž”αŸ‹αžŠαŸαžαžšαŸ†αž€αž·αž› αžŠαŸ‚αž›αž…αŸ†αž“αž½αž“αž•αžαžƒαŸ‚αžšαž˜αž½αž™αž…αŸ†αž“αž½αž“αžαŸ’αžšαžΌαžœαž”αžΆαž“αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž“αŸƒαžšαžΌαž”αž—αžΆαž–αŸ” αž”αŸ’αžšαžŸαž·αž“αž”αžΎαž–αž½αž€αžœαžΆαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαžŠαŸ„αž™αž‚αŸ’αž˜αžΆαž“αž”αž‰αŸ’αž αžΆαž“αŸ„αŸ‡ αž•αžαžŠαŸ‚αž›αž˜αžΆαž“αžšαžΌαž”αž—αžΆαž–αž‡αŸ†αž“αžΆαž“αŸ‹αž…αžΆαžŸαŸ‹αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž‰αŸ’αž…αž”αŸ‹ αž αžΎαž™αž•αžαžαŸ’αž˜αžΈαžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αž„αŸ’αž€αžΎαžαžŸαŸ’αžšαž”αž‚αŸ’αž“αžΆαŸ”

αž αŸ’αž‚αžΈαžαžΌαž”

αž™αžΎαž„αž”αŸ’αžšαžΎ GitOps αž€αŸ’αž“αž»αž„αž§αž‘αžΆαž αžšαžŽαŸαž“αŸαŸ‡ αžŠαŸ„αž™αžŸαžΆαžšαž™αžΎαž„αŸ–

  • αž€αžΆαžšαž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹ Git αž‡αžΆαž”αŸ’αžšαž—αž–αžαŸ‚αž˜αž½αž™αž“αŸƒαž€αžΆαžšαž–αž·αž
  • αž™αžΎαž„αž”αŸ’αžšαžΎ Git Operations αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž”αž„αŸ’αž€αžΎαž αž“αž·αž„αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ (αž˜αž·αž“αž…αžΆαŸ†αž”αžΆαž…αŸ‹αž˜αžΆαž“αž–αžΆαž€αŸ’αž™αž”αž‰αŸ’αž‡αžΆαž€αŸ’αžšαŸ…αž–αžΈ git tag/merge)

αž§αž‘αžΆαž αžšαžŽαŸ:

αž…αžΌαžšαž™αžΎαž„αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαžŠαŸαž›αŸ’αž’αž˜αž½αž™ - αžŠαžΎαž˜αŸ’αž”αžΈαž˜αžΆαž“αžƒαŸ’αž›αžΆαŸ†αž„αž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΌαžŠαž€αž˜αŸ’αž˜αžœαž·αž’αžΈ αž“αž·αž„αž˜αž½αž™αž‘αŸ€αžαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αŸ”

αžƒαŸ’αž›αžΆαŸ†αž„αž€αž˜αŸ’αž˜αžœαž·αž’αžΈ

αž“αŸαŸ‡αž‚αžΊαž‡αžΆ Python+Flask API αžŠαŸαžŸαžΆαž˜αž‰αŸ’αž‰αž”αŸ†αž•αž»αžαžŠαŸ‚αž›αžαŸ’αžšαž‘αž”αŸ‹αž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž”αž‡αžΆ JSON αŸ” αž™αžΎαž„αž“αžΉαž„αž”αž„αŸ’αž€αžΎαžαž€αž‰αŸ’αž…αž”αŸ‹αžαžΆαž˜αžšαž™αŸˆ GitlabCI αž αžΎαž™αžšαž»αž‰αž›αž‘αŸ’αž’αž•αž›αž‘αŸ… Gitlab Registry αŸ” αž“αŸ…αž€αŸ’αž“αž»αž„αž”αž‰αŸ’αž‡αžΈαžˆαŸ’αž˜αŸ„αŸ‡ αž™αžΎαž„αž˜αžΆαž“αž€αŸ†αžŽαŸ‚αž…αŸαž‰αž•αŸ’αžŸαžΆαž™αž–αžΈαžšαž•αŸ’αžŸαŸαž„αž‚αŸ’αž“αžΆαŸ–

  • wuestkamp/k8s-deployment-example-app:v1
  • wuestkamp/k8s-deployment-example-app:v2

αž—αžΆαž–αžαž»αžŸαž‚αŸ’αž“αžΆαžαŸ‚αž˜αž½αž™αž‚αžαŸ‹αžšαžœαžΆαž„αž–αž½αž€αžœαžΆαž‚αžΊαž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš JSON αžŠαŸ‚αž›αž”αžΆαž“αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αŸ” αž™αžΎαž„αž”αŸ’αžšαžΎαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž“αŸαŸ‡αžŠαžΎαž˜αŸ’αž”αžΈαž˜αžΎαž›αžƒαžΎαž‰αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αžαžΆαž˜αžŠαŸ‚αž›αž’αžΆαž…αž’αŸ’αžœαžΎαž‘αŸ…αž”αžΆαž“αžαžΆαžαžΎαž€αŸ†αžŽαŸ‚αžŽαžΆαž˜αž½αž™αžŠαŸ‚αž›αž™αžΎαž„αž€αŸ†αž–αž»αž„αž‘αžΆαž€αŸ‹αž‘αž„αž‡αžΆαž˜αž½αž™αŸ”

αžƒαŸ’αž›αžΆαŸ†αž„αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’

αž“αŸ…αž€αŸ’αž“αž»αž„ turnip αž“αŸαŸ‡αž™αžΎαž„αž“αžΉαž„αžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžαžΆαž˜αžšαž™αŸˆ GitlabCI αž‘αŸ… Kubernetes, .gitlab-ci.yml αž˜αžΎαž›αž‘αŸ…αžŠαžΌαž…αž“αŸαŸ‡:

image: traherom/kustomize-docker

before_script:
   - printenv
   - kubectl version

stages:
 - deploy

deploy test:
   stage: deploy
   before_script:
     - echo $KUBECONFIG
   script:
     - kubectl get all
     - kubectl apply -f i/k8s

   only:
     - master

αžŠαžΎαž˜αŸ’αž”αžΈαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαžœαžΆαžŠαŸ„αž™αžαŸ’αž›αž½αž“αž―αž„ αž’αŸ’αž“αž€αž“αžΉαž„αžαŸ’αžšαžΌαžœαž€αžΆαžš cluster αž’αŸ’αž“αž€αž’αžΆαž…αž”αŸ’αžšαžΎ GcloudαŸ–

gcloud container clusters create canary --num-nodes 3 --zone europe-west3-b

gcloud compute firewall-rules create incoming-80 --allow tcp:80

αž’αŸ’αž“αž€αžαŸ’αžšαžΌαžœαž€αžΆαžšαž”αŸ†αž”αŸ‚αž€ https://gitlab.com/wuestkamp/k8s-deployment-example-canary-infrastructure αž“αž·αž„αž”αž„αŸ’αž€αžΎαžαž’αžαŸαžš KUBECONFIG αž“αŸ…αž€αŸ’αž“αž»αž„ GitlabCI αžŠαŸ‚αž›αž“αžΉαž„αž˜αžΆαž“ config αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž…αžΌαž›αž”αŸ’αžšαžΎ kubectl αž‘αŸ…αž€αŸ’αžšαž»αž˜αžšαž”αžŸαŸ‹αž’αŸ’αž“αž€αŸ”

αž’αŸ’αž“αž€αž’αžΆαž…αž’αžΆαž“αž’αŸ†αž–αžΈαžšαž”αŸ€αž”αž‘αž‘αž½αž›αž”αžΆαž“αž–αŸαžαŸŒαž˜αžΆαž“αžŸαž˜αŸ’αž„αžΆαžαŸ‹αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž…αž„αŸ’αž€αŸ„αž˜ (Gcloud) αž“αŸ…αž‘αžΈαž“αŸαŸ‡.

αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ Yaml

αž“αŸ…αž€αŸ’αž“αž»αž„αžƒαŸ’αž›αžΆαŸ†αž„αž αŸαžŠαŸ’αž‹αžΆαžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’ αž™αžΎαž„αž˜αžΆαž“αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αŸ–

apiVersion: v1
kind: Service
metadata:
 labels:
   id: app
 name: app
spec:
 ports:
 - port: 80
   protocol: TCP
   targetPort: 5000
 selector:
   id: app
 type: LoadBalancer

αž“αž·αž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž“αŸ…αž€αŸ’αž“αž»αž„ deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: app
spec:
 replicas: 10
 selector:
   matchLabels:
     id: app
     type: main
 template:
   metadata:
     labels:
       id: app
       type: main
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v1
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

αž“αž·αž„αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž˜αž½αž™αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸ…αž€αŸ’αž“αž»αž„ deploy-canary.yaml:

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 0
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

αž…αŸ†αžŽαžΆαŸ†αžαžΆ app-deploy αž˜αž·αž“αž‘αžΆαž“αŸ‹αž˜αžΆαž“αž€αžΆαžšαž€αŸ†αžŽαžαŸ‹αž…αž˜αŸ’αž›αž„αžŽαžΆαž˜αž½αž™αž“αŸ…αž‘αžΎαž™αž‘αŸαŸ”

αž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ†αž”αžΌαž„

αžŠαžΎαž˜αŸ’αž”αžΈαž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ†αž”αžΌαž„ αž’αŸ’αž“αž€αž’αžΆαž…αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜αž”αŸ†αž–αž„αŸ‹ GitlabCI αžŠαŸ„αž™αžŠαŸƒαž“αŸ…αž›αžΎαžŸαžΆαžαžΆαž˜αŸαŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹αž˜αž€ kubectl αž‚αž½αžšαžαŸ‚αž…αŸαž‰αž›αž‘αŸ’αž’αž•αž›αžŠαžΌαž…αžαžΆαž„αž€αŸ’αžšαŸ„αž˜αŸˆ

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αž™αžΎαž„β€‹αžƒαžΎαž‰ app αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž‡αžΆαž˜αž½αž™ 10 replicas αž“αž·αž„ app-canary αž‡αžΆαž˜αž½αž™ 0. αžœαžΆαž€αŸαž˜αžΆαž“ LoadBalancer αžŠαŸ‚αž›αž™αžΎαž„αž’αžΆαž…αž…αžΌαž›αž”αŸ’αžšαžΎαž”αžΆαž“αžαžΆαž˜αžšαž™αŸˆ curl αžαžΆαž˜αžšαž™αŸˆ IP αžαžΆαž„αž€αŸ’αžšαŸ…αŸ–

while true; do curl -s 35.198.149.232 | grep label; sleep 0.1; done

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αž™αžΎαž„αžƒαžΎαž‰αžαžΆαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžŸαžΆαž€αž›αŸ’αž”αž„αžšαž”αžŸαŸ‹αž™αžΎαž„αžαŸ’αžšαž‘αž”αŸ‹αž˜αž€αžœαž·αž‰αžαŸ‚ β€œv1” αž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αŸ”

αž€αžΆαžšαž’αž“αž»αžœαžαŸ’αžαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary

αž‡αŸ†αž αžΆαž“αž‘αžΈ 1: αž…αŸαž‰αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž˜αž½αž™αž…αŸ†αž“αž½αž“

αž™αžΎαž„αž€αŸ†αžŽαžαŸ‹αž…αŸ†αž“αž½αž“αž…αž˜αŸ’αž›αž„αž‘αŸ… 1 αž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš deploy-canary.yaml αž“αž·αž„αžšαžΌαž”αž—αžΆαž–αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαŸ–

kind: Deployment
metadata:
 name: app-canary
spec:
 replicas: 1
 selector:
   matchLabels:
     id: app
     type: canary
 template:
   metadata:
     labels:
       id: app
       type: canary
   spec:
     containers:
     - image: registry.gitlab.com/wuestkamp/k8s-deployment-example-app:v2
       name: app
       resources:
         limits:
           cpu: 100m
           memory: 100Mi

αž“αŸ…αž€αŸ’αž“αž»αž„αž―αž€αžŸαžΆαžš deploy.yaml αž™αžΎαž„αž”αžΆαž“αž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž…αŸ†αž“αž½αž“αž…αž˜αŸ’αž›αž„αž‘αŸ…αž‡αžΆ 9αŸ–

kind: Deployment
metadata:
 name: app
spec:
 replicas: 9
 selector:
   matchLabels:
     id: app
...

αž™αžΎαž„αž‡αŸ†αžšαž»αž‰αž€αžΆαžšαž•αŸ’αž›αžΆαžŸαŸ‹αž”αŸ’αžαžΌαžšαž‘αžΆαŸ†αž„αž“αŸαŸ‡αž‘αŸ…αž€αžΆαž“αŸ‹αžƒαŸ’αž›αžΆαŸ†αž„αžŠαŸ‚αž›αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž“αžΉαž„αž…αžΆαž”αŸ‹αž•αŸ’αžαžΎαž˜ (αžαžΆαž˜αžšαž™αŸˆ GitlabCI) αž αžΎαž™αžƒαžΎαž‰αž‡αžΆαž›αž‘αŸ’αž’αž•αž›αŸ–

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αžŸαŸαžœαžΆαž€αž˜αŸ’αž˜αžšαž”αžŸαŸ‹αž™αžΎαž„αž“αžΉαž„αž…αž„αŸ’αž’αž»αž›αž‘αŸ…αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž‘αžΆαŸ†αž„αž–αžΈαžš αžŠαŸ„αž™αžŸαžΆαžšαž‘αžΆαŸ†αž„αž–αžΈαžšαž˜αžΆαž“αž€αž˜αŸ’αž˜αžœαž·αž’αžΈαž‡αŸ’αžšαžΎαžŸαžšαžΎαžŸαŸ” αžŠαŸ„αž™αžŸαžΆαžšαž€αžΆαžšαž…αŸƒαžŠαž“αŸ’αž™αž›αŸ†αž“αžΆαŸ†αžŠαžΎαž˜αžšαž”αžŸαŸ‹ Kubernetes αž™αžΎαž„αž‚αž½αžšαžαŸ‚αžƒαžΎαž‰αž€αžΆαžšαž†αŸ’αž›αžΎαž™αžαž”αž•αŸ’αžŸαŸαž„αŸ—αž‚αŸ’αž“αžΆαžŸαž˜αŸ’αžšαžΆαž”αŸ‹ ~10% αž“αŸƒαžŸαŸ†αžŽαžΎαŸ–

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αžŸαŸ’αžαžΆαž“αž—αžΆαž–αž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž“αŸƒαž€αž˜αŸ’αž˜αžœαž·αž’αžΈαžšαž”αžŸαŸ‹αž™αžΎαž„ (GitOps αž™αž€αž…αŸαž‰αž–αžΈ Git αž‡αžΆαž”αŸ’αžšαž—αž–αžαŸ‚αž˜αž½αž™αž“αŸƒαž€αžΆαžšαž–αž·αž) αž‚αžΊαž‡αžΆαžœαžαŸ’αžαž˜αžΆαž“αž“αŸƒαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αž–αžΈαžšαž‡αžΆαž˜αž½αž™αž“αžΉαž„αž€αžΆαžšαž…αž˜αŸ’αž›αž„αžŸαž€αž˜αŸ’αž˜ αž˜αž½αž™αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αŸ†αžŽαŸ‚αž“αžΈαž˜αž½αž™αŸ—αŸ”

~ 10% αž“αŸƒαž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αžŸαŸ’αž‚αžΆαž›αŸ‹αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈ αž αžΎαž™αžŸαžΆαž€αž›αŸ’αž”αž„αžŠαŸ„αž™αž’αž…αŸαžαž“αžΆαŸ” αž₯αž‘αžΌαžœαž“αŸαŸ‡αž‡αžΆαž–αŸαž›αžœαŸαž›αžΆαžŠαžΎαž˜αŸ’αž”αžΈαž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αž€αŸ†αž αž»αžŸαž“αŸ…αž€αŸ’αž“αž»αž„αž€αŸ†αžŽαžαŸ‹αž αŸαžαž» αž“αž·αž„αžαŸ’αžšαž½αžαž–αž·αž“αž·αžαŸ’αž™αž‘αž·αž“αŸ’αž“αž“αŸαž™αžŠαžΎαž˜αŸ’αž”αžΈαžŸαŸ’αžœαŸ‚αž„αžšαž€αž”αž‰αŸ’αž αžΆαŸ”

αž‡αŸ†αž αžΆαž“αž‘αžΈ 2: αž…αŸαž‰αž•αŸ’αžŸαžΆαž™αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαžŠαž›αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ”

αž™αžΎαž„αž”αžΆαž“αžŸαž˜αŸ’αžšαŸαž…αž…αž·αžαŸ’αžαžαžΆαž’αŸ’αžœαžΈαŸ—αžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž›αŸ’αž’ αž αžΎαž™αž₯αž‘αžΌαžœαž“αŸαŸ‡αž™αžΎαž„αžαŸ’αžšαžΌαžœαžŠαžΆαž€αŸ‹αž…αŸαž‰αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαžŠαž›αŸ‹αž’αŸ’αž“αž€αž”αŸ’αžšαžΎαž”αŸ’αžšαžΆαžŸαŸ‹αž‘αžΆαŸ†αž„αž’αžŸαŸ‹αŸ” αžŠαžΎαž˜αŸ’αž”αžΈαž’αŸ’αžœαžΎαžŠαžΌαž…αž“αŸαŸ‡αž™αžΎαž„αž‚αŸ’αžšαžΆαž“αŸ‹αžαŸ‚αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž– deploy.yaml αž€αžΆαžšβ€‹αžŠαŸ†αž‘αžΎαž„β€‹αž€αŸ†αžŽαŸ‚β€‹αžαŸ’αž˜αžΈβ€‹αž“αŸƒβ€‹αžšαžΌαž”αž—αžΆαž– αž“αž·αž„β€‹αž…αŸ†αž“αž½αž“β€‹αž“αŸƒβ€‹αž€αžΆαžšβ€‹αž…αž˜αŸ’αž›αž„β€‹αžŸαŸ’αž˜αžΎβ€‹αž“αžΉαž„ 10. αž€αŸ’αž“αž»αž„ deploy-canary.yaml αž™αžΎαž„β€‹αž€αŸ†αžŽαžαŸ‹β€‹αž…αŸ†αž“αž½αž“β€‹αž…αž˜αŸ’αž›αž„β€‹αžαŸ’αžšαž‘αž”αŸ‹β€‹αž˜αž€β€‹αžαŸ’αžšαžΉαž˜ 0αŸ” αž”αž“αŸ’αž‘αžΆαž”αŸ‹β€‹αž–αžΈβ€‹αž€αžΆαžšβ€‹αžŠαžΆαž€αŸ‹β€‹αž–αž„αŸ’αžšαžΆαž™ αž›αž‘αŸ’αž’αž•αž›β€‹αž“αžΉαž„β€‹αž˜αžΆαž“β€‹αžŠαžΌαž…β€‹αžαžΆαž„β€‹αž€αŸ’αžšαŸ„αž˜αŸ–

αž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™ Canary αž“αŸ…αž€αŸ’αž“αž»αž„ Kubernetes # 1: Gitlab CI

αžŠαžΎαž˜αŸ’αž”αžΈαžŸαž„αŸ’αžαŸαž”αŸ”

αžŸαž˜αŸ’αžšαžΆαž”αŸ‹αžαŸ’αž‰αž»αŸ† αž€αžΆαžšαžŠαŸ†αžŽαžΎαžšαž€αžΆαžšαž€αžΆαžšαžŠαžΆαž€αŸ‹αž–αž„αŸ’αžšαžΆαž™αžŠαŸ„αž™αžŠαŸƒ αžœαž·αž’αžΈαž“αŸαŸ‡αž‡αž½αž™αž±αŸ’αž™αž™αž›αŸ‹αž–αžΈαžšαž”αŸ€αž”αžŠαŸ‚αž›αžœαžΆαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž€αŸ†αžŽαžαŸ‹αžšαž…αž“αžΆαžŸαž˜αŸ’αž–αŸαž“αŸ’αž’αžŠαŸ„αž™αž”αŸ’αžšαžΎ k8s αž™αŸ‰αžΆαž„αž„αžΆαž™αžŸαŸ’αžšαž½αž›αŸ” αžŠαŸ„αž™αžŸαžΆαžš Kubernetes αž’αž“αž»αž‰αŸ’αž‰αžΆαžαž±αŸ’αž™αž’αŸ’αž“αž€αž’αŸ’αžœαžΎαž”αž…αŸ’αž…αž»αž”αŸ’αž”αž“αŸ’αž“αž—αžΆαž–αž’αŸ’αžœαžΈαŸ—αž‚αŸ’αžšαž”αŸ‹αž™αŸ‰αžΆαž„αžαžΆαž˜αžšαž™αŸˆ API αž‡αŸ†αž αžΆαž“αž‘αžΆαŸ†αž„αž“αŸαŸ‡αž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αžαžΆαž˜αžšαž™αŸˆαžŸαŸ’αž‚αŸ’αžšαžΈαž”αŸ”

αžšαžΏαž„αž˜αž½αž™αž‘αŸ€αžαžŠαŸ‚αž›αžαŸ’αžšαžΌαžœαž’αž“αž»αžœαžαŸ’αžαž‚αžΊαž…αŸ†αžŽαž»αž…αž”αž‰αŸ’αž…αžΌαž›αž’αŸ’αž“αž€αžŸαžΆαž€αž›αŸ’αž”αž„ (LoadBalancer αž¬αžαžΆαž˜αžšαž™αŸˆ Ingress) αžŠαŸ‚αž›αž˜αžΆαž“αžαŸ‚αž€αŸ†αžŽαŸ‚αžαŸ’αž˜αžΈαž”αŸ‰αž»αžŽαŸ’αžŽαŸ„αŸ‡αžŠαŸ‚αž›αž’αžΆαž…αž…αžΌαž›αž”αŸ’αžšαžΎαž”αžΆαž“αŸ” αžœαžΆαž’αžΆαž…αžαŸ’αžšαžΌαžœαž”αžΆαž“αž”αŸ’αžšαžΎαžŸαž˜αŸ’αžšαžΆαž”αŸ‹αž€αžΆαžšαžšαž»αž€αžšαž€αžŠαŸ„αž™αžŠαŸƒαŸ”

αž“αŸ…αž€αŸ’αž“αž»αž„αž’αžαŸ’αžαž”αž‘αž“αžΆαž–αŸαž›αž’αž“αžΆαž‚αž αž™αžΎαž„αž“αžΉαž„αž–αž·αž“αž·αžαŸ’αž™αž˜αžΎαž›αžŠαŸ†αžŽαŸ„αŸ‡αžŸαŸ’αžšαžΆαž™αžŸαŸ’αžœαŸαž™αž”αŸ’αžšαžœαžαŸ’αžαž·αž•αŸ’αžŸαŸαž„αž‘αŸ€αž αžŠαŸ‚αž›αž’αž“αž»αžœαžαŸ’αžαž—αžΆαž‚αž…αŸ’αžšαžΎαž“αž“αŸƒαž’αŸ’αžœαžΈαžŠαŸ‚αž›αž™αžΎαž„αž”αžΆαž“αž’αŸ’αžœαžΎαŸ”

αžŸαžΌαž˜αž’αžΆαž“αž’αžαŸ’αžαž”αž‘αž•αŸ’αžŸαŸαž„αž‘αŸ€αžαž“αŸ…αž›αžΎαž”αŸ’αž›αž€αŸ‹αžšαž”αžŸαŸ‹αž™αžΎαž„αž•αž„αžŠαŸ‚αžšαŸ–

αž”αŸ’αžšαž—αž–: www.habr.com

αž”αž“αŸ’αžαŸ‚αž˜αž˜αžαž·αž™αŸ„αž”αž›αŸ‹