Públic: freelancers i petits equips que necessiten un lliurament fiable i barat a Kubernetes.Aquesta és una guia llarga i pràctica amb un munt de codi copiable i explicacions addicionals. Títol: Dr Construïu imatges de Docker a GitHub Actions, etiqueteu cada imatge amb el comit SHA, premeu a GitHub Container Registry (GHCR) utilitzant el GITHUB_TOKEN incorporat, i desplegueu-les a Kubernetes amb Helm. Confia en els desplegaments de Kubernetes per a les actualitzacions de rodament, i les sondes de disponibilitat de filferro + vitalitat perquè els pods no tinguin trànsit fins que estiguin llestos (i es reiniciïn si s'enganxen). Tres errors recurrents que veig: (1) enviament: últim, (2) no esperant els llançaments, (3) donant CI clúster-admin. Fixes: etiqueta o digest-pin imatges, espera en el llançament, i els permisos de desplegament d'àmbit amb RBAC en l'espai de noms de destinació. (Kubernetes) Taula de continguts Per què aquesta pila s'adapta als freelancers L'arquitectura en una sola imatge Configuració única i context que necessitaràs Una petita aplicació de mostra (Node.js) que realment es pot executar Dockerfile: construcció multietapa, explicada Estructura i valors del gràfic del casc: què està passant i per què CI: GitHub Accions flux de treball per construir / etiqueta / empènyer (amb memòria cau) CD: Actualització del casc, temporades segures i controls de desplegament Les proves de salut que eviten el temps de descàrrega sorpresa Trencaclosques que veig setmanalment (i com evitar-los) RBAC mínim per CI (no més clúster-admin) Registres privats i imagePullSecrets (nota de GHCR) Rollbacks, qui fa què, i un ràpid “estic sa?” Un disseny reutilitzable i una llista de control de secrets Opcional: el mateix bucle amb Customize Apèndix: passos CI addicionals (proves, concurrència, controls de fum) Referències 1) Per què aquesta pila s'adapta als freelancers Quan estàs sol o treballant amb un petit equip, el temps que gastar eines d'adhesió junts és el temps que pot facturar. La combinació de sota manté el radi de l'explosió petit i les parts en moviment comprensibles: No es GitHub Actions + GHCR: ja estàs emmagatzemant el teu codi a GitHub; Actions executa les teves construccions i GHCR manté les teves imatges en el mateix límit de confiança. Amb els permisos de flux de treball adequats, el GITHUB_TOKEN incorporat és suficient per empènyer les imatges -no hi ha tokens addicionals per girar, no hi ha comptes addicionals per gestionar. (GitHub Docs) Els gràfics són només plantilles amb un lloc clar per als estàndards (values.yaml), i una manera senzilla d'enumerar-los per entorn. (Helm) Desenvolupaments de Kubernetes: les actualitzacions en moviment són la norma per defecte - Kubernetes substitueix gradualment els subs vells amb nous i només declara l'èxit després que el nou ReplicaSet estigui llest. 2) L'arquitectura en una sola imatge El darrer pas és important: fins que el desplegament és realment saludable (o temps fora), el que significa que les canonades verdes s'alinearan amb una aplicació saludable, no només "manifestes aplicades". ( ) your pipeline blocks Coberta 3) Configuració única i context que necessitaràs utilitzeu la instal·lació oficial per tal que les versions coincideixin amb la desviació compatible del vostre clúster (normalment ±1 menor). (Kubernetes) Helm v3 en el corredor. La pàgina oficial d'instal·lació documenta el guió que moltes persones utilitzen en CI. (Helm) Afegiu l'etiqueta OCI org.opencontainers.image.source al vostre Dockerfile perquè GHCR enllaci automàticament el paquet al vostre repo; utilitzeu GITHUB_TOKEN amb paquets: escriviu amb l'àmbit de les autoritzacions del flux de treball. (GitHub Docs) Si el teu En el cas que no estigui a l’abast de l’espai, s’haurà d’aplicar la regla “dins d’un mínim”. ) Why versions/skew matters: kubectl Coberta Una petita aplicació de mostra (Node.js) que realment es pot executar Dos terminis que mapen directament a les sondes de Kubernetes: // app/server.js import http from 'node:http'; const port = process.env.PORT || 3000; let ready = false; // Simulate warm-up work: DB connection, JIT, caches... setTimeout(() => (ready = true), 3000); const server = http.createServer((req, res) => { if (req.url === '/livez') return res.end('ok'); // liveness probe if (req.url === '/healthz') return res.end(ready ? 'ok' : 'starting'); // readiness probe res.writeHead(200, { 'content-type': 'text/plain' }); res.end('hello'); }); server.listen(port, () => console.log(`listening on ${port}`)); El mínim Així, es poden fer les proves ràpidament: package.json { "name": "demo-app", "type": "module", "scripts": { "start": "node app/server.js", "test": "node -e \"const http=require('http');http.get('http://127.0.0.1:3000',r=>process.exit(r.statusCode===200?0:1))\"" }, "dependencies": {} } El punt de i Kubernetes els tracta de manera diferent - el trànsit de portes; A partir de llavors s’haurà de tornar a instal·lar els contenidors. ( ) /healthz /livez readiness liveness Coberta Dockerfile: construcció multietapa, explicada Per què multietapa? les eines de construcció (compiladors, bundlers) no són necessàries en el temps d'execució. i les fases fan les imatges més petites, més ràpides i més segures. Els documents oficials de Docker recomanen explícitament les construccions de múltiples fases per a la producció. ( ) build runtime Docker Documentació # Dockerfile # -------- build stage -------- FROM node:20 AS build WORKDIR /app COPY package*.json ./ RUN npm ci --omit=dev COPY . . # leave only prod deps RUN npm prune --omit=dev # -------- runtime stage -------- FROM node:20-slim WORKDIR /app COPY --from=build /app ./ EXPOSE 3000 CMD ["node","app/server.js"] # helps GHCR link this image to your repo automatically LABEL org.opencontainers.image.source="https://github.com/your-org/your-repo" Si alguna vegada necessiteu imatges de múltiples arcs (arm64 portàtil, servidor amd64), i QEMU ho fan possible amb un flux de treball. Ens adherirem a un sol arc per a la velocitat. ( ) Buildx Docker Documentació 6) Estructura i valors del gràfic del casc: què està passant i per què Els gràfics del casc són carpetes amb un disseny específic; els estàndards viuen en Els temples viuen sota Podeu superar els defectes per entorn amb o en línia · ( ) values.yaml templates/ --values path.yaml --set key=value Helm chart/Chart.yaml apiVersion: v2 name: app description: Minimal demo app type: application version: 0.1.0 # chart version appVersion: "0.1.0" # your app version (for humans; not enforced) (Els defectes que superareu en CI) chart/values.yaml image: repository: ghcr.io/your-org/your-repo/app tag: "CHANGE_ME" # CI will set this to the commit SHA pullPolicy: IfNotPresent service: type: ClusterIP port: 80 targetPort: 3000 replicaCount: 2 resources: requests: { cpu: 100m, memory: 128Mi } limits: { cpu: 500m, memory: 256Mi } # optional if using private images # imagePullSecrets: # - name: ghcr-pull (Prova + actualització de rodament) chart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "app.fullname" . }} labels: app.kubernetes.io/name: {{ include "app.name" . }} spec: replicas: {{ .Values.replicaCount }} strategy: { type: RollingUpdate } selector: matchLabels: app.kubernetes.io/name: {{ include "app.name" . }} template: metadata: labels: app.kubernetes.io/name: {{ include "app.name" . }} spec: {{- if .Values.imagePullSecrets }} imagePullSecrets: {{- range .Values.imagePullSecrets }} - name: {{ .name }} {{- end }} {{- end }} containers: - name: app image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports: - containerPort: {{ .Values.service.targetPort }} readinessProbe: httpGet: { path: /healthz, port: {{ .Values.service.targetPort }} } initialDelaySeconds: 5 periodSeconds: 5 livenessProbe: httpGet: { path: /livez, port: {{ .Values.service.targetPort }} } initialDelaySeconds: 15 periodSeconds: 10 chart/templates/service.yaml apiVersion: v1 kind: Service metadata: name: {{ include "app.fullname" . }} spec: type: {{ .Values.service.type }} selector: app.kubernetes.io/name: {{ include "app.name" . }} ports: - port: {{ .Values.service.port }} targetPort: {{ .Values.service.targetPort }} Si prefereixes un enfocament més DRY, afegeix un La guia de les millors pràctiques de Helm cobreix com estructurar valors i ajudants de manera neta. ( ) _helpers.tpl El casc CI: Accions de GitHub per construir, etiquetar i empènyer (amb memòria cau) Utilitzarem les Accions oficials de Docker: , , i Imatge amb la imatge de Per tant, cada desplaçament és traçable i immutable. per · ( , ) setup-buildx login build-push commit SHA packages: write GITHUB_TOKEN GitHub Documents de GitHub .github/workflows/ci.yml name: ci on: push: branches: [ "main" ] permissions: contents: read packages: write # allow pushing to GHCR (least privilege) jobs: build-and-push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # optional: speed up local tests - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm test - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image uses: docker/build-push-action@v6 with: context: . push: true tags: ghcr.io/${{ github.repository }}/app:${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max Aquí teniu un parell de gotes: Els permisos de flux de treball han de permetre l'escriptura de paquets, o el GHCR rebutjarà els push. Podeu establir els paràmetres per defecte en la configuració de repo i encara restringir per flux de treball / tasca. (GitHub Docs) L'etiquetatge d'imatges amb org.opencontainers.image.source ajuda al GHCR a connectar el paquet de nou a la interfície de reproducció. (GitHub Docs) Buildx és la manera recomanada de construir imatges en Accions, amb el suport de memòria cau i multiarc documentat a la guia CI de Docker. Kubernetes tracta les referències d'imatge literalment. Les etiquetes fan que sigui més difícil saber el que s'està executant i poden travessar els paràmetres de política de retirada. (que ) per a una reproductibilitat perfecta—Kubernetes dóna suport als digestors nativament. ( ) Why SHA tags instead of :latest :latest digest image@sha256:... Coberta 8) CD: Actualització del casc, temporades segures i comprovacions de desplegament Apliqueu immediatament després d'una empenta reeixida. S'utilitza tant per primera vegada com per repetició. afegir (Bloc fins que estigui llest), (No espereu per sempre), i (Rollback automàtic en fallada). Després, com una xarxa de seguretat addicional, executeu per a fluir el progrés en el log de treball. ( , ) helm upgrade --install --wait --timeout --atomic kubectl rollout status El casc Coberta deploy: needs: build-and-push runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Install kubectl (official) run: | curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x kubectl && sudo mv kubectl /usr/local/bin/ - name: Install Helm run: curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash - name: Configure kubeconfig env: { KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_DATA }} } run: | mkdir -p $HOME/.kube echo "$KUBECONFIG_DATA" | base64 -d > $HOME/.kube/config - name: Helm upgrade (create or update) run: | helm upgrade --install app ./chart \ --namespace prod --create-namespace \ --set image.tag=${{ github.sha }} \ --wait --timeout=10m --atomic - name: Rollout status (extra verification) run: kubectl rollout status deploy/app -n prod --timeout=180s i El casc S'aconsegueix un nivell d'èxit / fracàs; Imprimeix el progrés per pas i dóna un feedback ràpid i llegible quan alguna cosa està fora. converteix les fallades en un retrocés automàtic, útil quan prefereixes ser segur que “meva actualitzat”. ( , ) Why both --wait kubectl rollout status --wait kubectl rollout status --atomic El casc Coberta 9) Les sondes de salut que eviten el temps de parada sorpresa Vostè pot tenir una actualització de rodament perfecte i encara servir errors si l'aplicació accepta el trànsit abans que s'escalfi. Evitar: porten els terminis de servei fins que el seu pod diu "preparat". En el cas de que l'aplicació no estigui en funcionament, el cubelet reiniciarà el contenidor després de repetides fallades. ( ) readiness probes Liveness probes Coberta Instruccions pràctiques de tuning: Si la seva aplicació necessita 20s per escalfar-se, ajusti inicialment DelaySeconds a la disponibilitat en conseqüència. Si l'aplicació ocasionalment bloqueja (per exemple, deadlock), prefereixi una sonda de vida HTTP o TCP que colpeixi un punt final o port trivial. Si l'aplicació és lenta per començar, afegiu una sonda d'arrencada per retardar la vida fins que s'acabi l'arrencada. (Kubernetes) 10) Pitfalls I see weekly (and how to avoid them) 10.1 Navegació :latest El que va malament: La mateixa etiqueta apunta a diferents bits amb el temps; la memòria cau i les peculiaritats de la política fan que no estigui clar si un node realment va treure la nova imatge. La solució: etiquetar imatges mitjançant comit SHA o utilitzar digests (@sha256:...). Kubernetes dóna suport a les referències de digest; sempre obtindrà la imatge exacta. 10.2 No esperar a les rellotges El que va malament: La seva canonada acaba "verda", però els usuaris veuen errors durant 30-60 segons perquè la implementació encara no s'ha convertit. La correcció: afegir --espera --timeout (i opcionalment --atòmic) a Helm, i executar l'estat de desplegament de kubectl perquè els errors es mostrin clarament en els registres. (Helm, Kubernetes) 10.3 CI sobre-privilegis (administrador de clústers) El que va malament: Un token que s'ha filtrat equival a un compromís de clúster complet. La solució: Crea un ServiceAccount + Role + RoleBinding amb l'espai de noms de l'objectiu, amb només els verbs i els recursos que necessita el gràfic. 11) RBAC mínim per CI (còpia/pasta) # rbac/deployer.yaml apiVersion: v1 kind: ServiceAccount metadata: name: helm-deployer namespace: prod --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: helm-deployer namespace: prod rules: - apiGroups: ["apps"] resources: ["deployments","replicasets"] verbs: ["get","list","watch","create","update","patch"] - apiGroups: [""] resources: ["services","configmaps","secrets"] verbs: ["get","list","watch","create","update","patch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get","list","watch","create","update","patch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: helm-deployer namespace: prod subjects: - kind: ServiceAccount name: helm-deployer namespace: prod roleRef: kind: Role name: helm-deployer apiGroup: rbac.authorization.k8s.io Això segueix el Principi: el SA només pot tocar l'espai de noms i els tipus de recursos que gestiona el gràfic. Si un token fuig, el dany es limita a aquells verbs / recursos en RBAC és el model d'autorització suportat en Kubernetes. ( ) least privilege prod Coberta d) Registres privats i (Càtedra de Gestió) Imatge secreta Imatge secreta Paquets públics del GHCR: qualsevol persona pot retirar de forma anònima; no es requereix secret. Paquets de GHCR privats: crea un secret del registre de Docker i el refereix a la teva especificació del pod (o l'afegeix al teu ServiceAccount). Crear un secret i utilitzar-lo en : prod kubectl create secret docker-registry ghcr-pull \ --docker-server=ghcr.io \ --docker-username=YOUR_GITHUB_USERNAME \ --docker-password=YOUR_GHCR_TOKEN_OR_PAT \ --docker-email=you@example.com \ -n prod Després en for prod: values.yaml imagePullSecrets: - name: ghcr-pull Els documents oficials mostren el mateix flux per a registres privats; el GHCR utilitza l'estàndard Docker auth. ( ) Coberta 13) Rollbacks, who does what, and a quick “am I healthy?” Dues línies poden ajudar-te: release history → . Helm helm history/rollback Historial de desplegament → kubectl rollout undo/status. Els comandaments típics: # See release history managed by Helm helm history app -n prod # Roll back to the previous release helm rollback app 1 -n prod # Verify the Deployment converges kubectl rollout status deploy/app -n prod --timeout=180s El casc ja automàticament torna a les fallades durant la actualització. És molt útil per a l'execució de l'execució manual o per a l'execució de l'execució manual. ( , ) --atomic kubectl rollout status Helm Coberta 14) Un disseny reutilitzable de repo i una llista de control de secrets repo-root/ app/ # your code Dockerfile chart/ Chart.yaml values.yaml values-staging.yaml values-prod.yaml templates/ deployment.yaml service.yaml _helpers.tpl rbac/ deployer.yaml .github/workflows/ci.yml Secrets (GitHub → Settings → Secrets and variables → Actions): KUBECONFIG_DATA – base64 kubeconfig per al desenvolupador de casc ServiceAccount. GITHUB_TOKEN – injectat automàticament; establir permisos de flux de treball: paquets: escriure per empènyer a GHCR (utilitzar repo/org per defecte o YAML). (GitHub Docs) 15) Optional: the same loop with Kustomize Kustomize Prefereixes les vinyes sense temple? is built into El teu pipeline es converteix en: build → push → El . It’s great for single-service repos and small customizations; Helm tends to be handier when you need packagability or your client already uses charts. ( ) Kustomize kubectl kubectl apply -k overlays/prod kubectl rollout status Coberta Quick sketch: kustomize/ base/ deployment.yaml service.yaml kustomization.yaml overlays/ prod/ kustomization.yaml # patches image tag to $GIT_SHA 16) Apèndix: passos CI addicionals (proves, concurrència, controls de fum) (Porta prèvia per 1 sol·licitud): A tiny smoke check after deploy - name: Port-forward and smoke test run: | kubectl -n prod port-forward svc/app 8080:80 & PF_PID=$! sleep 3 curl -fsS http://127.0.0.1:8080/healthz | grep -q "ok" kill $PF_PID Digest pinning (even stricter than tags): # Check the pushed image's digest docker buildx imagetools inspect ghcr.io/${OWNER}/${REPO}/app:${GITHUB_SHA} # Then set in values-prod.yaml: # image: # repository: ghcr.io/${OWNER}/${REPO}/app # tag: "" # leave empty when using a digest # digest: "sha256:..." Si voleu plantar l'ús de digest en el casc, ajusteu l'estança d'imatge i la plantilla: # values.yaml (allow either tag OR digest) image: repository: ghcr.io/your-org/your-repo/app tag: "CHANGE_ME" digest: "" # templates/deployment.yaml (image reference) image: "{{ .Values.image.repository }}{{- if .Values.image.digest -}}@{{ .Values.image.digest }}{{- else -}}:{{ .Values.image.tag }}{{- end }}" El cubisme entén És la manera més determinista de fer-ho. what you built. ( ) @sha256: Exactament Coberta Addició Dues i inclou QEMU si cal. Els documents de Docker mostren tots dos. ( ) Multi-arch builds (if you need arm64): platforms: linux/amd64,linux/arm64 build-push-action Docker Documentació 17) Referències Kubernetes (Rolling update behavior & concepts). (Kubernetes) Rolling updates overview (tutorial). (Kubernetes) kubectl status rollout (comand reference). (Kubernetes) Probes (liveness, readiness, startup). (Kubernetes) Imatges: tags, digests, i imagePullSecrets. (Kubernetes) autorització RBAC (oficial). (Kubernetes) Instal·lar kubectl i nota de desviació de la versió. (Kubernetes) and flags ( , , ). ( ) Installing Helm (CI script). ( ) Chart structure & values reference and best practices. ( ) Helm helm upgrade --install --wait --atomic Helm Helm Helm GitHub Actions & GHCR Publishing Docker images with Actions. (GitHub Docs) Utilitzant GITHUB_TOKEN amb permisos de menys privilegis. (GitHub Docs) Treballant amb el registre de contenidors (GHCR) i etiquetes OCI. (GitHub Docs) Docker oficial GitHub Actions: setup-buildx, login, build-push. (GitHub) Docker's CI guide for GitHub Actions. (Docker Documentation) Docker Multi-stage builds (per què/com), bones pràctiques, multiplataforma. Reflexions de tancament This is the path I reach for when a client says: Escala d'un sol servei a molts, i cada part d'ella és explicable a les persones que no són plataformes: "Volem un desplegament fiable aquesta setmana, no una reconstrucció de la plataforma". One chart, one workflow, one registry. Imatges immutables (etiquetes de SHA o digestors), sondes que reflecteixen la salut real de l'aplicació i llançaments que esperen. Permisos de desplegament objectiu, no clúster-admin. Estigueu connectats Si us ha agradat aquest article i voleu explorar més sobre el desenvolupament web, sentiu-vos lliures de connectar amb mi en diverses plataformes: Següent hackernoon.com Títol hashnode.com El twitter.com · Instagram.com La cartera V1 Els vostres comentaris i preguntes sempre són benvinguts.Continua aprenent, codificant i creant increïbles aplicacions web.