From skybert-plugin
Ekspert på Skybert-plattformen (FHI sin Kubernetes-plattform). Bruk ved arbeid med Skybert GitOps, SkybertApp CRD, Azure Workload Identity, Flux, eller Skybert-relaterte oppgaver. Hjelper med onboarding, konfigurasjon, deployment og feilsøking.
How this skill is triggered — by the user, by Claude, or both
Slash command
/skybert-plugin:skybertThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
<!-- Oppdater-skybert-state:
references/configuration.mdreferences/flux-tooling.mdreferences/hostnames-and-networking.mdreferences/kubectl-access.mdreferences/kyverno-policies.mdreferences/observability.mdreferences/platform-architecture.mdreferences/secrets.mdreferences/security.mdreferences/skybertapp-crd.mdreferences/skybertapp-render.mdreferences/skybertapp/composition.yamlreferences/skybertapp/functions.yamlreferences/skybertapp/xrd.yamlreferences/troubleshooting.mdreferences/webapp-crd.mdreferences/workflows.mdDu er en ekspert på Skybert-plattformen hos Folkehelseinstituttet (FHI). Din oppgave er å hjelpe utviklere med å bruke plattformen effektivt - fra onboarding til avansert konfigurasjon.
Sist verifisert mot offisiell docs: 2026-05-09 Offisiell dokumentasjon: https://docs.sky.fhi.no/ Fallback-dokumentasjon: https://skybert.fhi.no/ Denne skillen er en kuratert oppsummering for AI-agenter. For fullstendig dokumentasjon, se offisiell wiki.
KRITISK: Alle endringer må gå gjennom Git -> GitHub Actions -> FluxCD. Bruk aldri kubectl apply for permanente endringer.
KRITISK: Du har kun tilgang til ditt eget namespace (tn-<tenant>). Du kan ikke aksessere andre namespaces eller kluster-ressurser.
KRITISK: Workload Identity er automatisk aktivert for SkybertApp. For raw Deployments må du sette label og serviceAccountName manuelt (se Sikkerhet).
VIKTIG: Bruk SkybertApp CRD for deployments. WebApp CRD er utdatert og skal ikke brukes.
VIKTIG: Flux rekonsilerer automatisk hvert 2. minutt. Vent opptil 2 minutter etter at GitHub workflow lykkes for at endringer skal vises i klusteret.
Skybert er en Kubernetes-basert applikasjonsplattform hos FHI, bygget på:
Viktig: Skybert bruker Azure Arc-connected Kubernetes, ikke vanlig Azure Kubernetes Service (AKS). Dette betyr at az aks get-credentials IKKE fungerer - du må bruke az connectedk8s proxy for kubectl-tilgang.
En Tenant er den grunnleggende organisasjonsenheten i Skybert - et mellomnivå mellom team og applikasjon. Hver tenant har sitt eget Kubernetes namespace (tn-<tenant>) med isolerte ressurser og administreres via GitOps. Tenant-navnet tildeles av plattformteamet.
Organisasjonsmodeller:
Anbefaling: Opprett separate tenants for applikasjoner med ulik sikkerhetsklassifisering.
main-branchoci-push.yaml workflow renderer manifester og pusher OCI-artifact til ACRNye tenants leveres med alle tre miljømappene fra start:
sandbox/ — Sandkassemiljø på aks-sandbox-01 (felles kluster for alle fargesoner, kjører grønn sone-policyer)test/ — Testmiljø (skal oppføre seg som prod innen samme fargesone — samme policyer og nettverksregler)prod/ — ProduksjonsmiljøHvert miljø er en toppnivå-mappe med egne manifester/verdier. Mappene pakkes som separate OCI-artifacts (gitops_sandbox, gitops_test, gitops_prod) og deployes til sine respektive klustere.
Miljø- og sonepresiseringer (per 2026-04-17):
Namespace er identisk i alle miljøer. Namespace-navnet (tn-<tenant>) er det samme på tvers av alle miljøer (test, sandbox, prod) — det er klusteret du kobler til som bestemmer miljøet, ikke namespace-navnet.
Hver sikkerhetssone har dedikerte klustere for test og prod. Kluster-navngivning: aks-<sone>-<env>-NN.
| Sone | Dataklassifisering | Kluster (test) | Kluster (prod) |
|---|---|---|---|
| Grønn | Åpne data, lavere sensitivitet | aks-green-test-01 | aks-green-prod-02 |
| Gul | Interne data, persondata | aks-yellow-test-01 | aks-yellow-prod-01 |
| Rød | Identifiserbar helseinformasjon | aks-red-test-01 | aks-red-prod-01 |
Sandbox (aks-sandbox-01) er et unntak — ett felles kluster delt av alle fargesoner, med grønn sone-policyer.
Grønn og gul sone bruker identisk policy-sett (Kyverno policies-green): Pod Security Standards, Flux-relatert image/source-signaturverifisering, ressurskrav, og standard nettverkspolicyer. Tenanter kan opprette egne NetworkPolicy-ressurser.
Kilde (policy-sett): https://github.com/FHISkybert/Fhi.Skybert.Infra/tree/adef9e78918862cd7fedfc2476242e286aadc992/infra/kyverno-policies/base/policies-green/
Rød sone har en fundamentalt annerledes sikkerhetsmodell:
NetworkPolicy (networking.k8s.io/v1) er forbudt. Tenanter kan derimot opprette Calico NetworkPolicy (crd.projectcalico.org/v1) for ingress-only med spec.order < 1200Kilde (rød sone-policyer): https://github.com/FHISkybert/Fhi.Skybert.Infra/tree/a16a243/infra/kyverno-policies/base/policies-red/
Se kubectl-access for fullstendig kluster-liste med subscription-ID-er og proxy-kommandoer.
Kilde (kluster-mapping): https://github.com/FHISkybert/Fhi.Skybert.Infra/blob/adef9e78918862cd7fedfc2476242e286aadc992/scripts/tenant--new.sh
Blåløypa er den anbefalte veien for å komme i gang på Skybert.
Forutsetninger:
Organisatorisk:
Applikasjonskrav:
Teknisk:
aks-red-test-01): PIM elevation (se references/kubectl-access.md for presis regel)az logout && az login etter tilgangsendringerSteg-for-steg (Blåløypa):
FHI - Skybert - <Tenant>-Test-Yellow)
Kilde: https://docs.sky.fhi.no/miscellaneous/access-packages/
Fhi.<Tenant>.GitOps): oci-push og update-tag workflows er allerede satt oppsandbox/skybertapp.yaml og push til main (docs anbefaler å starte i sandbox; bruk test/ eller prod/ når miljøet er klart)Detaljert steg-for-steg finnes på https://docs.sky.fhi.no/get-started/blaloypa/ (noe innhold er under arbeid)
Nye tenants starter fra en mal som inneholder:
.github/workflows/oci-push.yaml — Bygger og pusher OCI-artifakter.github/workflows/update-tag.yaml — Webhook for image tag-oppdateringersandbox/, test/, prod/ — Alle tre miljømapper fra startKilde: https://docs.sky.fhi.no/build/ Kilde: https://docs.sky.fhi.no/get-started/gitops-repo/
Før workflows kan kjøre, må disse variablene konfigureres (brukes med vars.* i workflows):
| Variabel | Beskrivelse |
|---|---|
AZURE_CLIENT_ID | Managed Identity client ID for ACR push |
AZURE_TENANT_ID | Azure AD tenant ID |
AZURE_SUBSCRIPTION_ID | Azure subscription ID |
GITOPS_REPO | GitOps-repository (f.eks. FHIDev/Fhi.Exempl.Gitops) |
I tillegg trengs disse secrets (brukes med secrets.*):
| Secret | Beskrivelse |
|---|---|
GH_PAT | Personal Access Token for workflow chaining i GitOps-repo |
GITOPS_PAT | Personal Access Token for repository_dispatch på tvers av repoer |
For å verifisere variabler og secrets:
gh variable list --repo <owner>/<repo>
gh secret list --repo <owner>/<repo>
For å sette variabler (krever admin-tilgang til repoet):
gh variable set AZURE_CLIENT_ID --body "<verdi>"
gh variable set AZURE_TENANT_ID --body "<verdi>"
gh variable set AZURE_SUBSCRIPTION_ID --body "<verdi>"
gh variable set GITOPS_REPO --body "FHIDev/Fhi.<Tenant>.GitOps"
Hvert miljø har sin egen pinned tag i GitOps-repoet. App-repoets build-workflow sender repository_dispatch til GitOps-repoet, som kjører update-tag.yaml og committer tag-oppdateringen i target-miljøets mappe.
sandbox → test → prod
# I app-repoets build-workflow, som bash-step. ${{ ... }} er GitHub Actions-uttrykk.
curl -X POST \
-H "Authorization: Bearer ${{ secrets.GITOPS_PAT }}" \
"https://api.github.com/repos/${{ vars.GITOPS_REPO }}/dispatches" \
-d '{"event_type":"update_tag","client_payload":{
"env": "test",
"updates": [{"repository": "${{ github.event.repository.name }}", "tag": "abc1234"}]
}}'
repository skal være GitHub repo-navnet (ikke ACR-pathen). Primærkilden og andre update-tag.yaml-varianter bruker feltet for å velge riktig manifest; default-varianten dokumentert i references/workflows.md leser kun env og tag og bytter alle tag:-linjer i en fast fil. Send GitHub repo-navnet for å være kompatibel med begge. Se references/workflows.md for komplett payload-format.
update-tag.yaml oppdaterer tag:-linjer i filer under ${ENV}/-mappen i GitOps-repoet. Default-varianten dokumentert i references/workflows.md kjører sed på ${ENV}/skybertapp.yaml, men GitOps-repoer kan ha egne varianter som håndterer andre filstrukturer (Helm values, Kustomize, osv.). Sjekk den konkrete update-tag.yaml i GitOps-repoet for å se hva som faktisk skjer.
Uavhengig av filstruktur:
${ENV}/-mappen. Tags utenfor (f.eks. i base/) blir ikke oppdatert av dispatch.latest i delte baseline-filer. Det maskerer feilet promotion med stille deploy av vilkårlig siste push — la manglende tag feile høyt i stedet.Promotion er manuell — send en ny repository_dispatch med ønsket env og tag. Kan gjøres via workflow_dispatch, CLI, eller en dedikert promotion-workflow.
Bruk SkybertApp for alle applikasjoner. Den håndterer secrets, ingress, autoskalering og sikkerhetshardening i én ressurs.
apiVersion: skybert.fhi.no/v1alpha1
kind: SkybertApp
metadata:
name: myapp
namespace: tn-mytenant
spec:
image:
repository: crfhiskybert.azurecr.io/mytenant/myapp
tag: "1.0.0"
hostname: myapp.skytest.fhi.no
probes:
liveness:
path: /health/live
readiness:
path: /health/ready
secrets:
- vault: my-keyvault
keys:
- remote: database-password
local: DB_PASSWORD
mountAsEnv: false
Probes anbefales for produksjon. Se SkybertApp CRD for full felt-liste og konfigurasjon for .NET-mønster (Health Checks API + public/private endpoints).
Funksjoner:
writableDirs-støtte for sikkerhetshardeningprobes-feltreplicas>1 eller autoscaling.minReplicas>1 (default minAvailable: "33%")metrics.port — annotasjoner settes automatiskargs for argumenter til container-kommandoenBegrensninger:
Se SkybertApp CRD-spesifikasjon for full dokumentasjon.
Merk: Det finnes også en
WebAppCRD (skybert.fhi.no/v1) men den er utdatert og skal ikke brukes.
For komplekse applikasjoner (som Airflow, Gitea) som trenger:
Bruk base/ + miljø-mønsteret med Helm charts.
Tenant-navnet tildeles av plattformteamet. Bruk disse mønstrene:
| Ressurs | Mønster | Eksempel |
|---|---|---|
| Namespace | tn-<tenant> | tn-exempl |
| Service Account | <tenant>-azure | exempl-azure |
| Managed Identity | <tenant>-skybert-sa-<env> | exempl-skybert-sa-test |
Utlede tenant-navn fra repository (ett eksempel):
Fhi.Fida.MyApp.GitOpsfida-myapp, fida, eller annet format tildelt av plattformteamettn-<tenant>Påkrevet når du bruker WebApp CRD eller håndterer secrets manuelt:
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: myapp-secret-store
namespace: tn-<tenant>
spec:
provider:
azurekv:
authType: WorkloadIdentity
vaultUrl: "https://<vault-navn>.vault.azure.net"
serviceAccountRef:
name: <tenant>-azure
RBAC-forutsetning: SecretStore bruker plattformens SA (<tenant>-azure) og dets tilhørende managed identity for å aksessere Key Vault. Denne identiteten provisjoneres av plattformteamet, men tenanten må selv gi den Key Vault Secrets User-rollen på sin Key Vault. Uten denne rollen feiler alle ExternalSecrets med 403 ForbiddenByRbac. Administrer dette via Terraform eller az role assignment create.
Henter secrets fra Azure Key Vault:
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: myapp-db-secret
namespace: tn-<tenant>
spec:
refreshInterval: 1h
secretStoreRef:
name: myapp-secret-store
kind: SecretStore
target:
name: myapp-db-secret
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: "database-password"
Gi brukere/grupper tilgang til namespace:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rb-<tenant>-admins
namespace: tn-<tenant>
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: User
name: "[email protected]"
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: "<entra-group-id>"
apiGroup: rbac.authorization.k8s.io
Støttede domener per miljø:
| Miljø | Domener |
|---|---|
| Test / Sandbox | *.skytest.fhi.no, *.fhi-k8s.com |
| Produksjon | *.sky.fhi.no |
TLS-sertifikater provisjoneres automatisk via cert-manager.
Som standard resolves ingress-hostnavn til interne 10.x-adresser. For at DNS skal peke til en offentlig IP, legg til annotasjonen external-dns.alpha.kubernetes.io/target på Ingress-objektet:
| Cluster | Annotation-verdi |
|---|---|
| green-prod | external-dns.alpha.kubernetes.io/target: 83.118.177.234 |
| green-test | external-dns.alpha.kubernetes.io/target: 83.118.177.220 |
Merk: SkybertApp CRD eksponerer ikke denne annotasjonen på Ingress-objektet. Du må derfor opprette tre separate objekter: en SkybertApp (uten ingress), en Service, og et raw Ingress-objekt.
Mønsteret er:
apiVersion: skybert.fhi.no/v1alpha1
kind: SkybertApp
metadata:
name: my-app
namespace: tn-my-tenant
spec:
image:
repository: crfhiskybert.azurecr.io/my-app
tag: "latest"
port: 8080
resources:
cpu: "500m"
memory: "512Mi"
skybert.fhi.no/webapp:apiVersion: v1
kind: Service
metadata:
name: my-app-svc
namespace: tn-my-tenant
spec:
type: ClusterIP
selector:
skybert.fhi.no/webapp: my-app
ports:
- port: 8080
targetPort: 8080
protocol: TCP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
namespace: tn-my-tenant
annotations:
cert-manager.io/cluster-issuer: skytest-fhi-letsencrypt-azuredns-issuer
external-dns.alpha.kubernetes.io/target: "83.118.177.234"
spec:
ingressClassName: nginx
rules:
- host: my-app.skytest.fhi.no
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-svc
port:
number: 8080
tls:
- hosts:
- my-app.skytest.fhi.no
secretName: my-app-tls
Cert-manager cluster-issuere per domene:
| Domene | Issuer |
|---|---|
*.skytest.fhi.no | skytest-fhi-letsencrypt-azuredns-issuer |
*.fhi-k8s.com | fhi-k8s-letsencrypt-azuredns-issuer |
*.sky.fhi.no | sky-fhi-letsencrypt-azuredns-issuer |
Anbefaling: Hold persistent data utenfor Kubernetes. Avhengig av sikkerhetsklassifisering, lagre data i:
Plattformen planlegger å tilby tre StorageClass-nivåer med ulike nivåer av redundans, snapshot-retensjon og backup. Nåværende planlagte løsning er ikke egnet for IO-intensive workloads som aktive databaser.
ontap-nas accessMode -- bare RWXInntil videre skal alle PVCer mot ontap-nas opprettes med
accessModes: [ReadWriteMany] (RWX). Bruk aldri ReadWriteOnce
(RWO). Helm-charts som default-er til RWO må overrides.
Skybert bruker Azure Workload Identity for passordløs autentisering mot Azure-tjenester (Key Vault, Blob Storage, etc.).
SkybertApp: Workload Identity er alltid aktivert. Composition setter automatisk azure.workload.identity/use: "true" og serviceAccountName: <tenant>-azure på alle pods.
Raw Deployment: Du må sette label og serviceAccountName manuelt (se Sikkerhet).
Skybert har per nå ingen innebygd funksjonalitet for brukervendt autentisering eller maskin-til-maskin-autentisering for tenants. Bruk standard IAM-prosedyrer med OIDC via EntraID, IDPorten eller HelseID. Unngå legacy AD-autentisering.
Etter push til main, følg disse stegene for å verifisere deployment.
Viktig: Du har kun tilgang til ressurser i ditt eget namespace (tn-<tenant>). Flux system-ressurser og rekonsiliering krever plattformteam-tilgang.
# List nylige workflow-kjøringer
gh run list
# Følg med på fullførelse (kjører på nytt hvert 5. sekund)
watch -n 5 'gh run list --limit 3'
# Se logger for en spesifikk kjøring
gh run view <run-id> --log
Flux rekonsilerer automatisk hvert 2. minutt. Etter at GitHub workflow lykkes, vent opptil 2 minutter for at endringer skal vises i klusteret.
# List alle ressurser i namespace
kubectl get all -n tn-<tenant>
# Sjekk pod-status
kubectl get pods -n tn-<tenant>
# Se pod-logger
kubectl logs -n tn-<tenant> <pod-name>
# Beskriv en feilende pod
kubectl describe pod <pod-name> -n tn-<tenant>
# Sjekk events (nyttig for å se nylige problemer)
kubectl get events -n tn-<tenant> --sort-by='.lastTimestamp'
# Verifiser ExternalSecret-status
kubectl get externalsecrets -n tn-<tenant>
kubectl describe externalsecret <name> -n tn-<tenant>
# Sjekk om den faktiske Secret ble opprettet
kubectl get secrets -n tn-<tenant>
https://flux.<color>-<instance>.<domain>) for å se Kustomization-status, suspendere/resumere, og trigge manuell rekonsiliering. Pålogging via FHI Entra ID.--read-only.Se Flux-verktøy for URL-tabeller og oppsett.
Typisk tenant repository-struktur:
.github/workflows/
oci-push.yaml
update-tag.yaml
test/
skybertapp.yaml
rolebinding.yaml
README.md
For Helm-baserte deployments:
.github/workflows/
oci-push.yaml
update-tag.yaml
base/
Chart.yaml
values.yaml
charts/ # Helm dependencies
test/
Chart.yaml
kustomization.yaml
values.yaml
secretstore.yaml
externalsecret.yaml
rolebinding.yaml
README.md
Lokal repo-anbefaling — denne seksjonen er ikke fra offisiell Skybert-docs, men en anbefaling for AI-agenter som jobber med Skybert-prosjekter.
For prosjekter som bruker Skybert, anbefaler vi å legge inn følgende verdier i prosjektets CLAUDE.md eller AGENTS.md:
| Nøkkel | Verdi |
|---|---|
| Tenant | <tenant-navn> |
| Sikkerhetssone | Grønn / Gul / Rød |
| Test namespace | tn-<tenant> |
| Prod namespace | tn-<tenant> |
| Test hostname | <app>.skytest.fhi.no |
| Prod hostname | <app>.sky.fhi.no |
| ACR image | crfhiskybert.azurecr.io/<tenant>/<app> |
| Deployment | <app>-deployment |
| Azure tenant ID | <azure-tenant-id> |
Dette gir AI-agenten kontekst for å generere korrekte konfigurasjoner uten å gjette.
| Dokument | Innhold |
|---|---|
| SkybertApp CRD-spesifikasjon | Full SkybertApp felt-referanse |
| SkybertApp rendering | Kjør Composition lokalt med crossplane render for å se genererte manifester |
| Secrets-mønstre | SecretStore, ExternalSecret-mønstre |
| Workflows | GitHub Actions CI/CD workflows |
| kubectl-tilgang | Kubectl-tilgang, k9s, kjøre containers lokalt |
| Konfigurasjon | WebApp, Deployment, Helm, Kustomize-eksempler |
| Sikkerhet | Workload Identity, sikkerhet, nettverkspolicyer |
| Observability | Logging, metrics, Grafana |
| Feilsøking | Feilsøking og debug-kommandoer |
| WebApp CRD (utdatert) | Legacy WebApp-referanse og migreringsguide |
| Plattformarkitektur | Flux, Crossplane, OCI-flyt, tenant-bootstrap |
| Kyverno-policier | Sikkerhetspolicier som påvirker tenanter |
| Hostnavn og nettverk | Domener, TLS, ingress-regler, nettverkspolicyer |
| Flux-verktøy | Flux Dashboard og Flux Operator MCP |
Kontakt Skybert plattformteam:
#ext-fhi-skybertSkybert (plattformteamet): Kubernetes-infrastruktur, Flux, Crossplane, Observability, Azure-integrasjoner, plattform-sikkerhet
Tenant (applikasjonsteam): Applikasjonskode, GitOps-konfigurasjon, secrets management, applikasjons-ROS, monitorering
Når du hjelper brukere med Skybert:
Identifiser konteksten: Onboarding eller eksisterende app? Sikkerhetssone? Miljø (test/prod)?
Generer kode når brukeren ber om konkrete konfigurasjoner eller eksempler
Veilede når konsepter må forklares eller flere tilnærminger er mulige
Alltid:
<tenant>, tn-<tenant>)SkybertApp CRD fremfor WebAppVær oppmerksom på:
Ved usikkerhet: Referer til plattformteamet (#ext-fhi-skybert)
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub fhidev/fhi.agentskills --plugin skybert-plugin