All skills
microsoft avatar

/azure-kubernetes-app-deploy

@a8f19b4
by microsoftmicrosoft/skills3.1k stars
351

Use when deploying an existing web application or API to an already-running Azure Kubernetes Service cluster. Detects the framework, generates a Dockerfile and Kubernetes manifests, validates against AKS Deployment Safeguards, and deploys with verification. WHEN: deploy app to AKS, deploy to existing AKS cluster, containerize app for Kubernetes, generate K8s manifests for Azure, set up CI/CD for AKS, my AKS deployment is failing safeguard checks, I have a Django/Express/Spring Boot app to run on AKS. DO NOT USE FOR: creating or provisioning an AKS cluster (use azure-kubernetes), assessing migration to AKS Automatic (use azure-kubernetes-automatic-readiness), or deploying to non-AKS targets like Web Apps, Container Apps, or Functions.

Use this Skill: https://skilld.dev/gh/microsoft/skills/azure-kubernetes-app-deploy

This session only. Nothing lands on disk.

knowledge-packsframeworksflask.md

≈1.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Flask Knowledge Pack

Applies to: Projects detected with requirements.txt, pyproject.toml, or Pipfile containing flask

Quick Reference

Property Value
Signal files requirements.txt/pyproject.toml/Pipfile containing flask
Default port 8000 prod (5000 dev — never in prod)
Health path /health + /ready
Base template templates/dockerfiles/python.Dockerfile (+ references/base-images.md)

Health Endpoints

Flask does not include health check endpoints — they must be defined explicitly in application code:

Minimal health route

from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/health")
def health():
    return jsonify(status="ok"), 200

Readiness route with database check

from flask import jsonify
from sqlalchemy import text

@app.route("/ready")
def ready():
    try:
        db.session.execute(text("SELECT 1"))
        return jsonify(status="ready"), 200
    except Exception:
        return jsonify(status="not ready"), 503

Probe configuration in Deployment manifest

livenessProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 15
  timeoutSeconds: 3
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /ready
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 3
  failureThreshold: 3

Note: Flask apps behind gunicorn start quickly (typically <3s), so initialDelaySeconds: 5 is sufficient — much lower than JVM-based frameworks.


Database Profiles

Flask does not have a built-in profile system. Database configuration is typically driven by environment variables:

ORM / Driver Package(s) Connection String Env Var
Flask-SQLAlchemy flask-sqlalchemy, psycopg2-binary SQLALCHEMY_DATABASE_URI
SQLAlchemy direct sqlalchemy, psycopg2-binary DATABASE_URL
psycopg2 direct psycopg2-binary DATABASE_URL

Important: Flask-SQLAlchemy reads the connection string from app.config["SQLALCHEMY_DATABASE_URI"], which is typically set via os.environ.get("SQLALCHEMY_DATABASE_URI") or os.environ.get("DATABASE_URL"). Ensure the env var name matches what the app expects.

Environment variables for PostgreSQL on AKS

env:
  - name: SQLALCHEMY_DATABASE_URI
    value: "postgresql://{{IDENTITY_NAME}}@{{PG_SERVER_NAME}}.postgres.database.azure.com:5432/{{DB_NAME}}?sslmode=require"
  - name: SECRET_KEY
    valueFrom:
      secretKeyRef:
        name: {{APP_NAME}}-secrets
        key: secret-key

Secret for SECRET_KEY

Flask requires SECRET_KEY for session signing, CSRF tokens, and any use of flask.session. Never hardcode it — store it in a Kubernetes Secret:

apiVersion: v1
kind: Secret
metadata:
  name: {{APP_NAME}}-secrets
type: Opaque
stringData:
  secret-key: "<generate-a-random-string>"

ConfigMap pattern

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{APP_NAME}}-config
data:
  SQLALCHEMY_DATABASE_URI: "postgresql://{{IDENTITY_NAME}}@{{PG_SERVER_NAME}}.postgres.database.azure.com:5432/{{DB_NAME}}?sslmode=require"

Workload Identity with azure-identity

See references/workload-identity.md for connection patterns. Requires azure-identity package.


Writable Paths (DS012 Compliance)

When readOnlyRootFilesystem: true is set, Flask apps typically only need /tmp writable:

  • Uploaded files use /tmp as the default staging directory for request.files
  • Temporary processing may write intermediate results to /tmp

Required volume mount

volumes:
  - name: tmp
    emptyDir: {}
containers:
  - name: app
    volumeMounts:
      - name: tmp
        mountPath: /tmp

No other writable paths are typically needed for production Flask apps.


Resource Sizing

Flask with Gunicorn runs multiple worker processes. Size for the number of workers (default: 2-4).

Resource Request Limit
CPU 150m 500m
Memory 128Mi 256Mi

Port Configuration

  • Development port: 5000 (flask run default — do not use in production)
  • Production port: 8000 (gunicorn convention)
  • CLI flag: --bind 0.0.0.0:8000 passed to gunicorn
  • Env var override: PORT (read via gunicorn --bind 0.0.0.0:$PORT or in app code int(os.environ.get("PORT", 8000)))
  • Workers formula: 2 * CPU_CORES + 1 — override at runtime via WEB_CONCURRENCY env var
  • Entry point variants: gunicorn "app:app" (module-level) or gunicorn "myapp:create_app()" (application factory)

Gunicorn logs the port on startup: Listening at: http://0.0.0.0:8000


Build Commands

Tool Install Command
pip pip install --no-cache-dir -r requirements.txt
Poetry poetry install --only main --no-interaction

Ensure gunicorn is listed in requirements.txt or pyproject.toml production dependencies.


Common Issues on AKS

Issue Symptom Fix
Running dev server in production Single-threaded, poor performance, WARNING: This is a development server in logs Use gunicorn as the ENTRYPOINT — never use flask run or app.run() in production containers
SECRET_KEY not set RuntimeError: The session is unavailable because no secret key was set, CSRF failures Set SECRET_KEY via a Kubernetes Secret and reference it as an env var in the Deployment manifest
Flask binds to localhost Connection refused from Kubernetes probes Pass --bind 0.0.0.0:8000 to gunicorn — the Flask dev server defaults to 127.0.0.1 which is unreachable from outside the container
Gunicorn not installed ModuleNotFoundError: No module named 'gunicorn' Ensure gunicorn is in requirements.txt or pyproject.toml main dependencies — it is often only in dev dependencies or missing entirely
DB connections not closed sqlalchemy.exc.TimeoutError: QueuePool limit, PostgreSQL max_connections exhaustion Configure pool size with SQLALCHEMY_ENGINE_OPTIONS = {"pool_size": 5, "max_overflow": 10, "pool_recycle": 300} and match PostgreSQL max_connections

Source: SKILL.md on GitHub

1 warning1mo3 checks · Risk SAFE
  • Gen Agent Trust Hub1mo

    This skill facilitates the deployment of applications to Azure Kubernetes Service (AKS) by automating Dockerfile generation and Kubernetes manifest creation. It incorporates security best practices such as AKS Deployment Safeguards and Azure Workload Identity. No significant security considerations were identified; external resource references and tool usage align with the skill's intended deployment purpose.

  • Socket1mo

    No alerts

  • Snyk1mo

    Risk: MEDIUM · 2 issues

Signed by skilld at a8f19b4. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 2 months ago
metadata
{
  "author": "Microsoft",
  "version": "1.0.0"
}

README badge

README badge for microsoft/skills/azure-kubernetes-app-deploy