Python on Kubernetes
Garantindo escalabilidade em aplicações produtivas
BIANCA ROSA
tech lead @ stone
Agenda
- Criando uma app Flask
- Dockerfile + docker-compose
- Subindo sua imagem Docker
- Kubernetes 101
- Testando num cluster local
- Processo de build & deploy
Criando uma app Flask
Dica: escreva suas app base nas linguagens que você mais usa e evolua ela.
Dockerfile
FROM python:3.7.2-alpine3.7
RUN pip install pipenv
COPY Pipfile Pipfile
COPY Pipfile.lock Pipfile.lock
RUN pipenv install --system --deploy --ignore-pipfile
COPY . /app
WORKDIR /app
CMD ["gunicorn", "app.main:app", "-w", "4", "-b", "0.0.0.0:5000", "-t", "1000"]
docker build . -t k8s-flask-app
docker-compose
version: "3"
services:
web:
build:
context: .
command: gunicorn app.main:app --workers=4 --bind 0.0.0.0:5000 --reload
volumes:
- .:/app
ports:
- "5000:5000"
docker-compose up -d
Subindo sua imagem Docker
docker tag <image-id> <docker-hub-username>/k8s-flask-app docker push <docker-hub-username>/k8s-flask-app
Kubernetes 101
Plataforma para gerenciar workloads e serviços contêinerizados.
Pods
Pods são a menor unidade computacional que roda dentro de um cluster Kubernetes.
ReplicaSet
Quando falamos de ReplicaSet, queremos garantir a disponibilidade de um número fixo e específico de pods.
Deployments
Um deployment é o estado desejado de seus Pods e ReplicaSets.
Configmaps
Permitem que a gente tenha configurações desacopladas de uma aplicação contêinerizada.
Secrets
Um secret é um objeto que contém dados sensíveis como senhas, tokens ou chaves.
apiVersion: v1
kind: ConfigMap
metadata:
name: k8s-flask-app-env
data:
NOT_SO_SECRET_VARIABLE: $(NOT_SO_SECRET_VARIABLE)
configmap.yaml
apiVersion: v1
kind: Secret
metadata:
name: k8s-flask-app-secrets
type: Opaque
stringData:
SECRET_VARIABLE: $(SECRET_VARIABLE)
secrets.yaml
apiVersion: v1
kind: Service
metadata:
name: k8s-flask-app
spec:
ports:
- port: 5000
targetPort: 5000
protocol: TCP
name: http
selector:
app: k8s-flask-app
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: k8s-flask-app
spec:
backend:
serviceName: k8s-flask-app
servicePort: 5000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: k8s-flask-app
labels:
app: k8s-flask-app
spec:
replicas: 8
selector:
matchLabels:
app: k8s-flask-app
template:
metadata:
labels:
app: k8s-flask-app
spec:
containers:
- name: k8s-flask-app
image: biancarosa/k8s-flask-app
envFrom:
- configMapRef:
name: k8s-flask-app-env
- secretRef:
name: k8s-flask-app-secrets
ports:
- containerPort: 5000
deployment.yaml
Testando num cluster local
minikube start kubectl apply -f kubernetes/configmap.yaml kubectl apply -f kubernetes/secrets.yaml kubectl apply -f kubernetes/deployment.yaml
Subindo num cluster existente
** demo **
Processo de build & deploy
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
stages:
- stage: Test
jobs:
- job: Test
steps:
- task: UsePythonVersion@0
displayName: 'Use Python 3.7'
inputs:
versionSpec: '3.7'
architecture: 'x64'
- script: pip install pipenv
displayName: 'Install pipenv'
- script: pipenv install --system --dev --deploy --ignore-pipfile
displayName: 'Install dependencies'
- script: make coverage
displayName: 'Run tests'
- script: make lint
displayName: 'Run lint'
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testResultsFiles: '**/test-*.xml'
testRunTitle: 'Publish test results for Python 3.7'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'
- stage: BuildAndPush
jobs:
- job: BuildAndPush
steps:
- task: Docker@2
inputs:
containerRegistry: 'dockerhub'
repository: 'biancarosa/k8s-flask-app'
command: 'buildAndPush'
Dockerfile: 'Dockerfile'
tags: |
$(Build.BuildId)
latest
- stage: Deploy
jobs:
- job: Deploy
steps:
- task: Kubernetes@1
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceEndpoint: 'k8s-flask-app-cluster'
command: 'apply'
arguments: '-f kubernetes/configmap.yaml'
secretType: 'dockerRegistry'
containerRegistryType: 'Azure Container Registry'
- task: Kubernetes@1
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceEndpoint: 'k8s-flask-app-cluster'
command: 'apply'
arguments: '-f kubernetes/secrets.yaml'
secretType: 'dockerRegistry'
containerRegistryType: 'Azure Container Registry'
- task: Kubernetes@1
inputs:
connectionType: 'Kubernetes Service Connection'
kubernetesServiceEndpoint: 'k8s-flask-app-cluster'
command: 'apply'
arguments: '-f kubernetes/deployment.yaml'
secretType: 'dockerRegistry'
containerRegistryType: 'Azure Container Registry'
pipeline.yaml
Python on Kubernetes
By Bianca Rosa
Python on Kubernetes
- 1,145