Dit artikel is oorspronkelijk gepubliceerd op Devhouse Spindle op 4 augustus 2022. Wil je graag de Engelse versie lezen, bekijk dan de blog op onze Engelse site.
Na de eerste masterclass van ons dev event was het tijd om onze kennis over GitOps te delen. Om alle developers in staat te stellen met het microservices platform te werken, heeft ons infra team een template gemaakt waarmee ontwikkelaars zelf makkelijk een nieuwe service kunnen maken en deployen zonder tussenkomst van infra. In dit artikel lees je hoe we dit hebben gedaan en hoe we de complexiteit van Kubernetes voor developers hiermee hebben verhuld.
GitOps lijkt op DevOps, maar GitOps wordt gebruikt voor infrastructuur. Deze infrastructuur wordt volledig beschreven door configuratiebestanden. Om de huidige staat van de infrastructuur te vergelijken met de gewenste staat (zoals die beschreven staat in de configuratiebestanden), wordt een tool gebruikt. Deze tool voert een aantal acties uit om de gewenste en de huidige toestand op elkaar af te stemmen. Dit wordt gewoonlijk “infrastructuur als code” genoemd, aangezien de configuratiebestanden kunnen worden gerepresenteerd of gegenereerd door code.
Waarom zou je al die moeite doen om je infrastructuur zo op te zetten? Omdat infrastructuur als code een groot aantal voordelen heeft:
GitOps is niet alleen infrastructuur als code. Zoals de naam al aangeeft, heeft het ook iets te maken met Git. Het is misschien triviaal, maar het idee is dat de infrastructuur van code wordt opgeslagen in een Git repository. Dit zorgt ervoor dat er een geschiedenis is van veranderingen aan de infrastructuur en het biedt een solide manier om samen te werken. Meer specifiek dicteert GitOps dat elke verandering wordt gemaakt (gedeployed) door gewoon een git commit te doen. De hele pijplijn van testen, reviewen, etc. tot de uiteindelijke implementatie moet worden geautomatiseerd met CI/CD. Het idee is dat de enige ingang om veranderingen in de infrastructuur aan te brengen Git is.
In ons microservice platform gebruiken we het woord GitOps niet alleen om de workflow te beschrijven zoals hierboven is uitgelegd, we gebruiken het om het hele microservice platform te beschrijven. Het microservice platform is een platform-as-a-service (PaaS), gebouwd met in gedachten developers zonder kennis van infrastructuur of operations. We wilden een platform bouwen met moderne technologieën, zonder de gebruikers van het platform te belasten met het leren van al deze technologieën. We deden dit door niet alleen GitOps te gebruiken voor de infrastructuur zelf, maar ook voor de diensten die op het platform worden ingezet.
Een van de doelen van ons microservice platform is om teams in staat te stellen hun eigen DevOps te doen. Het creëren en inzetten van een nieuwe dienst vereist weinig kennis van de onderliggende technologieën en – ook belangrijk – vereist nul interactie met het infrateam. Andere aspecten van DevOps zoals monitoring, alerting, dashboarding, loginspectie en meer, worden allemaal automatisch geconfigureerd door de GitOps workflow. Ontwikkelaars hebben zelf toegang tot de tooling. Dit stelt teams in staat om eigenaar te zijn van hun dienst, van ontwikkeling tot inzet en onderhoud. Het vermindert ook de werkdruk op het infrateam en neemt hen gedeeltelijk weg als knelpunt, zodat de ontwikkeling van het platform niet wordt vertraagd.
De volgende afbeelding geeft een high level overzicht van het microservice platform:
Het huidige platform is gebouwd op de AWS-cloud. We hebben geprobeerd het platform zo cloud agnostisch mogelijk te bouwen, zodat we de flexibiliteit hebben om naar een andere cloud over te stappen of het platform zelfs on-premise te verplaatsen (wat uiteindelijk ons doel is).
Kubernetes draait bovenop de cloud, of on-premise infrastructuur. Voorlopig gebruiken we AWS EKS. Naast Kubernetes zijn er de nodige netwerkcomponenten (load balancers) en optionele databases die niet op Kubernetes worden gehost.
ArgoCD en Vault worden bovenop Kubernetes geleverd, en samen met wat andere kerncomponenten (Ingress-NGINX, cert-manager, etc.) vormt dit het basisplatform. Terraform wordt gebruikt om de basis te leveren en te onderhouden, het kan de infrastructuur vanaf het begin leveren (op een paar handmatige handelingen na, in verband met privacy en DNS). Dit stelt ons in staat om snel op te schalen naar andere regio’s, of in rampscenario’s de hele infrastructuur te slopen en opnieuw op te bouwen.
ArgoCD – geleverd in de basislaag – kan het nu overnemen van Terraform bij het leveren van verdere platformdiensten. Iets verderop zal ik uitleggen wat ArgoCD is, zie het voor nu maar als Terraform op Kubernetes.
In deze laag worden alle aanvullende platformdiensten – die niet nodig zijn bij het bootstrappen – geprovisioned. Dit omvat, maar is niet beperkt tot:
Voor deze diensten heeft provisioning met ArgoCD om meerdere redenen de voorkeur boven Terraform:
Kubernetes is gebouwd met een eenvoudig idee: je vertelt het welke resources je gedefinieerd wilt hebben in YAML-bestanden, en Kubernetes zorgt ervoor dat de resources er ook daadwerkelijk zijn en blijven. Een resource kan van alles zijn. Kubernetes is voornamelijk gebouwd rond containerorkestratie, dus de belangrijkste resources zijn dingen in en rond containers. Kubernetes is echter niet beperkt tot deze resources. Door Custom Resource Definitions (CRD’s) te definiëren en controllers in te zetten, kan Kubernetes worden uitgebreid met vrijwel elke resource. Hoewel het idee eenvoudig is, kan het bouwen van dingen in Kubernetes complex zijn. Dat komt omdat je domeinkennis nodig hebt om de resources te schrijven. En om het nog ingewikkelder te maken, kan het domein worden uitgebreid met CRD’s. Die last willen we developers niet opleggen.
Kubectl is het nieuwe ssh. Beperk de toegang en gebruik het alleen voor deployments als er geen betere tooling beschikbaar is.
Kelsey Hightower
Helm is een nuttige abstractie over Kubernetes YAML’s om het modulair en meer DRY te maken. Het probleem blijft echter dat je nog steeds domeinkennis van Kubernetes-resources nodig hebt. Helm code kan ook erg lastig zijn om goed te krijgen: fouten maken in YAML, uitgebreid met Go templating, is maar al te gemakkelijk.
De oplossing die we voor dit probleem hebben ontwikkeld is een holodeck-service Helm template (chart).
Alle diensten die op ons microservice platform worden ontwikkeld, gebruiken de holodeck-service Helm template. De template stelt ontwikkelaars in staat om configuratievariabelen in te stellen (via omgevingsvariabelen), geheimen in te laden (vanuit Vault), een database-instantie aan te vragen (via Crossplane), en nog veel meer. Het enige wat developers moeten weten zijn de beschikbare parameters in de Helm template. De template genereert de benodigde Kubernetes YAML voor de dienst. De complexiteit van Kubernetes wordt nu voor de ontwikkelaar verborgen door de abstractie. Ons infrateam heeft kennis van Kubernetes en diverse andere infrastructuurcomponenten. Met deze kennis onderhouden en voegen ze functies toe aan de Helm template, waardoor functies via parameters beschikbaar komen voor developers.
global:
domain: services
service: python-example
holodeck-service:
secrets:
enabled: true
envVarsFromVault:
WEATHER_API_KEY: WEATHER_API_KEY
FASTSTREAM_CREDS: FASTSTREAM_CREDS
envVars:
SENTRY_DSN:
value: ""
WEATHER_BASE_URL:
value: "<https://api.openweathermap.org>"
ingress:
rewrite: true
postgres:
enabled: true
storage: 10 # GiB
migrate:
command: ["alembic", "upgrade", "head"]
redis:
enabled: true
helm/values.yaml
Diensten kunnen nu worden ingezet op Kubernetes met Helm. Concreet konden we vanuit de GitLab CI-pijplijn Helm upgrade aanroepen om te deployen. We kwamen een paar problemen tegen met deze aanpak:
ArgoCD is een geweldige tool die een aantal van deze problemen kon oplossen, en meer! ArgoCD is “Declarative GitOps voor Kubernetes“. Het monitort één of meer Git repositories. Bij elke commit zal het de resources in Kubernetes bijwerken (via Helm of native YAML’s).
We hebben ArgoCD ingesteld om een “single source of truth” repository te monitoren, genaamd services-root. De repository bevat een JSON-bestand per dienst, per omgeving. De JSON beschrijft welke git commit (en Docker image tag) van de service repository live moet staan in de omgeving. Bijvoorbeeld:
{
"cluster": "staging",
"service": "python-example",
"imageTag": "a2a7d76d9f6af65f96fd46cc92bcee7f065d8514",
"targetRevision": "a2a7d76d9f6af65f96fd46cc92bcee7f065d8514"
}
Een ApplicationSet is geconfigureerd om wijzigingen in de services-root repository te bekijken. Voor elk JSON-bestand wordt een Application resource aangemaakt. De Application resource triggert ArgoCD om een git commit van de repository te checken, en de Helm chart toe te passen op Kubernetes, wat resulteert in de deployment van de dienst.
We hebben ons gericht op het gebruiksgemak van het platform voor developers: het verbergen van de complexiteit van Kubernetes en een heleboel andere tools die nodig zijn om een solide PaaS te bouwen. Tijdens de masterclass deed ik een demo die de stappen liet zien die een ontwikkelaar zou moeten nemen om een nieuwe dienst te maken en te deployen. Deze stappen zijn:
Kijkend naar deze stappen zijn we zeker geslaagd in ons doel om developers in staat te stellen het platform te gebruiken zonder hulp van het infrateam. Missie volbracht!
In de afgelopen jaren hebben we veel geschreven over ondernemen, zelfsturend werken, de handigste tools en nog veel meer. Dus leef je uit!
Ga naar het blogoverzicht