L'auteur a sélectionné lesDiversity in Tech Fund pour recevoir un don dans le cadre du programmeWrite for DOnations.
introduction
Pulumi est un outil pour créer, déployer et gérer une infrastructure à l'aide de code écrit dans des langages de programmation à usage général. Il prend en charge l’automatisation de tous les services gérés de DigitalOcean, tels que les droplets, les bases de données gérées, les enregistrements DNS et les clusters Kubernetes, en plus de la configuration des applications. Les déploiements sont effectués à partir d'une interface de ligne de commande conviviale, qui s'intègre également à une grande variété de systèmes CI / CD populaires.
Pulumi prend en charge plusieurs langues, mais dans ce didacticiel, vous utiliserezTypeScript, une version à typage statique deJavaScript qui utilise le runtime deNode.js. Cela signifie que vous bénéficierez d'un support IDE et d'une vérification lors de la compilation qui vous aideront à vous assurer que vous avez configuré les bonnes ressources, utilisé les bons slugs, etc., tout en étant toujours en mesure d'accéder aux modulesNPM pour les tâches utilitaires.
Dans ce didacticiel, vous allez provisionner un cluster DigitalOceanKubernetes, une application Kubernetes à charge équilibrée et un domaine DNS DigitalOcean qui rend votre application disponible sous un nom de domaine stable de votre choix. Tout cela peut être provisionné en 60 lignes d'infrastructure en tant que code et en un seul geste de ligne de commandepulumi up
. Après ce tutoriel, vous serez prêt à construire de manière productive de puissantes architectures cloud en utilisant l’infrastructure Pulumi en tant que code qui exploite toute la surface de DigitalOcean et de Kubernetes.
Conditions préalables
Pour suivre ce tutoriel, vous aurez besoin de:
-
Un compte DigitalOcean sur lequel déployer des ressources. Si vous n'en avez pas déjà un,register here.
-
Un jeton d'API DigitalOcean pour effectuer des déploiements automatisés. Generate a personal access token here et gardez-le à portée de main car vous l'utiliserez à l'étape 2.
-
Étant donné que vous allez créer et utiliser un cluster Kubernetes, vous devrezinstall
kubectl
. Ne vous inquiétez pas de le configurer davantage - vous le ferez plus tard. -
Vous écrirez votre code d'infrastructure sous TypeScript, vous aurez donc besoin de Node.js 8 ou version ultérieure. Download it here ou installez-leusing your system’s package manager.
-
Vous utiliserez Pulumi pour déployer l'infrastructure, vous aurez donc besoin deinstall the open source Pulumi SDK.
-
Pour exécuter l'étape 5 facultative, vous aurez besoin d'un nom de domaine configuré pour utiliser les serveurs de noms DigitalOcean. This guide explique comment procéder pour le bureau d'enregistrement de votre choix.
[[step-1 -—- scaffolding-a-new-project]] == Étape 1 - Scaffolding d'un nouveau projet
La première étape consiste à créer un répertoire qui stockera votre projet Pulumi. Ce répertoire contiendra le code source de vos définitions d'infrastructure, en plus des fichiers de métadonnées décrivant le projet et ses dépendances NPM.
Tout d'abord, créez le répertoire:
mkdir do-k8s
Ensuite, déplacez-vous dans le répertoire nouvellement créé:
cd do-k8s
À partir de maintenant, exécutez les commandes à partir de votre répertoiredo-k8s
nouvellement créé.
Ensuite, créez un nouveau projet Pulumi. Il existe différentes manières d'accomplir cela, mais la manière la plus simple est d'utiliser la commandepulumi new
avec le modèle de projettypescript
. Cette commande vous demandera d’abord de vous connecter à Pulumi pour que votre projet et l’état de déploiement soient enregistrés, puis créera un projet TypeScript simple dans le répertoire en cours:
pulumi new typescript -y
Ici, vous avez passé l'option-y
à la commandenew
qui lui dit d'accepter les options de projet par défaut. Par exemple, le nom du projet est tiré du nom du répertoire actuel, de même quedo-k8s
. Si vous souhaitez utiliser différentes options pour le nom de votre projet, élidez simplement les-y
.
Après avoir exécuté la commande, répertoriez le contenu du répertoire avecls
:
ls
Les fichiers suivants seront maintenant présents:
OutputPulumi.yaml index.ts node_modules
package-lock.json package.json tsconfig.json
Le fichier principal que vous allez modifier estindex.ts
. Bien que ce tutoriel utilise uniquement ce fichier, vous pouvez organiser votre projet comme bon vous semble en utilisant les modules Node.js. Ce tutoriel décrit également une étape à la fois, en exploitant le fait que Pulumi peut détecter et déployer de manière incrémentielle uniquement ce qui a changé. Si vous préférez, vous pouvez simplement remplir le programme entier et tout déployer en une seule fois en utilisantpulumi up
.
Maintenant que vous avez échafaudé votre nouveau projet, vous êtes prêt à ajouter les dépendances nécessaires pour suivre le didacticiel.
[[step-2 -—- add-dependencies]] == Étape 2 - Ajout de dépendances
L'étape suivante consiste à installer et à ajouter des dépendances sur les packages DigitalOcean et Kubernetes. Tout d'abord, installez-les à l'aide de NPM:
npm install @pulumi/digitalocean @pulumi/kubernetes
Cela téléchargera les packages NPM, les plugins Pulumi, et les enregistrera en tant que dépendances.
Ensuite, ouvrez le fichierindex.ts
avec votre éditeur préféré. Ce tutoriel utilisera nano:
nano index.ts
Remplacez le contenu de vosindex.ts
par ce qui suit:
index.ts
import * as digitalocean from "@pulumi/digitalocean";
import * as kubernetes from "@pulumi/kubernetes";
Cela rend le contenu complet de ces packages disponible pour votre programme. Si vous tapez"digitalocean."
à l'aide d'un IDE qui comprend TypeScript et Node.js, vous devriez voir une liste des ressources DigitalOcean prises en charge par ce package, par exemple.
Enregistrez et fermez le fichier après avoir ajouté le contenu.
[.note] #Note: Nous utiliserons un sous-ensemble de ce qui est disponible dans ces packages. Pour une documentation complète des ressources, des propriétés et des API associées, veuillez vous référer à la documentation API appropriée pour les packages@pulumi/digitalocean
et@pulumi/kubernetes
.
#
Vous allez ensuite configurer votre jeton DigitalOcean afin que Pulumi puisse provisionner les ressources de votre compte:
pulumi config set digitalocean:token YOUR_TOKEN_HERE --secret
Notez l'indicateur--secret
, qui utilise le service de chiffrement de Pulumi pour chiffrer votre jeton, en vous assurant qu'il est stocké dans cyphertext. Si vous préférez, vous pouvez utiliser la variable d'environnementDIGITALOCEAN_TOKEN
à la place, mais vous devrez vous rappeler de la définir chaque fois que vous mettez à jour votre programme, alors que l'utilisation de la configuration la stocke et l'utilise automatiquement pour votre projet.
Dans cette étape, vous avez ajouté les dépendances nécessaires et configuré votre jeton d'API avec Pulumi afin que vous puissiez provisionner votre cluster Kubernetes.
[[step-3 -—- provisioning-a-kubernetes-cluster]] == Étape 3 - Provisionnement d'un cluster Kubernetes
Vous êtes maintenant prêt à créer un cluster DigitalOcean Kubernetes. Commencez par rouvrir le fichierindex.ts
:
nano index.ts
Ajoutez ces lignes à la fin de votre fichierindex.ts
:
index.ts
...
const cluster = new digitalocean.KubernetesCluster("do-cluster", {
region: digitalocean.Regions.SFO2,
version: "latest",
nodePool: {
name: "default",
size: digitalocean.DropletSlugs.DropletS2VPCU2GB,
nodeCount: 3,
},
});
export const kubeconfig = cluster.kubeConfigs[0].rawConfig;
Ce nouveau code alloue une instance dedigitalocean.KubernetesCluster
et définit un certain nombre de propriétés dessus. Cela inclut l'utilisation dessfo2
region slug, la version prise en charge de Kuberneteslatest
, less-2vcpu-2gb
Droplet size slug et indique le nombre souhaité de trois instances de Droplet. N'hésitez pas à en changer, mais sachez que DigitalOcean Kubernetes n'est disponible que dans certaines régions au moment de la rédaction de cet article. Vous pouvez vous référer auxproduct documentation pour des informations mises à jour sur la disponibilité de la région.
Pour une liste complète des propriétés que vous pouvez configurer sur votre cluster, reportez-vous auxKubernetesCluster
API documentation.
La dernière ligne de cet extrait de code exporte leskubeconfig
file du cluster Kubernetes résultant afin qu'il soit facile à utiliser. Les variables exportées sont imprimées sur la console et accessibles aux outils. Vous l'utiliserez momentanément pour accéder à notre cluster à partir d'outils standards commekubectl
.
Vous êtes maintenant prêt à déployer votre cluster. Pour ce faire, exécutezpulumi up
:
pulumi up
Cette commande prend le programme, génère un plan pour créer l'infrastructure décrite et effectue une série d'étapes pour déployer ces modifications. Cela fonctionne pour la création initiale d'infrastructure en plus de pouvoir différer et mettre à jour votre infrastructure lorsque des mises à jour ultérieures sont effectuées. Dans ce cas, la sortie ressemblera à ceci:
OutputPreviewing update (dev):
Type Name Plan
+ pulumi:pulumi:Stack do-k8s-dev create
+ └─ digitalocean:index:KubernetesCluster do-cluster create
Resources:
+ 2 to create
Do you want to perform this update?
yes
> no
details
Cela indique que procéder à la mise à jour créera un seul cluster Kubernetes nommédo-cluster
. L'inviteyes/no/details
nous permet de confirmer qu'il s'agit du résultat souhaité avant que des modifications ne soient réellement apportées. Si vous sélectionnezdetails
, une liste complète des ressources et de leurs propriétés s'affiche. Choisissezyes
pour commencer le déploiement:
OutputUpdating (dev):
Type Name Status
+ pulumi:pulumi:Stack do-k8s-dev created
+ └─ digitalocean:index:KubernetesCluster do-cluster created
Outputs:
kubeconfig: "..."
Resources:
+ 2 created
Duration: 6m5s
Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/1
La création du cluster prend quelques minutes, mais il sera alors opérationnel et leskubeconfig
complets seront imprimés sur la console. Enregistrez leskubeconfig
dans un fichier:
pulumi stack output kubeconfig > kubeconfig.yml
Et puis utilisez-le aveckubectl
pour exécuter n'importe quelle commande Kubernetes:
KUBECONFIG=./kubeconfig.yml kubectl get nodes
Vous recevrez une sortie similaire à celle-ci:
OutputNAME STATUS ROLES AGE VERSION
default-o4sj Ready 4m5s v1.14.2
default-o4so Ready 4m3s v1.14.2
default-o4sx Ready 3m37s v1.14.2
À ce stade, vous avez configuré l’infrastructure sous forme de code et disposez d’une méthode reproductible pour créer et configurer de nouveaux clusters DigitalOcean Kubernetes. Dans la prochaine étape, vous construirez par dessus pour définir l'infrastructure de Kubernetes dans le code et apprendre à les déployer et à les gérer de la même manière.
[[step-4 -—- deploying-an-application-to-your-cluster]] == Étape 4 - Déploiement d'une application sur votre cluster
Ensuite, vous allez décrire la configuration d’une application Kubernetes en utilisant l’infrastructure en tant que code. Ce sera composé de trois parties:
-
Un objet
Provider
, qui indique à Pulumi de déployer les ressources Kubernetes sur le cluster DigitalOcean, plutôt que la valeur par défaut de toutkubectl
configuré pour l'utiliser. -
AKubernetes Deployment, qui est la manière standard de Kubernetes de déployer une image de conteneur Docker qui est répliquée sur n'importe quel nombre de pods.
-
AKubernetes Service, qui est le moyen standard de dire à Kubernetes d'équilibrer la charge de l'accès sur un ensemble cible de pods (dans ce cas, le déploiement ci-dessus).
C'est unreference architectureassez standard pour être opérationnel avec un service à charge équilibrée dans Kubernetes.
Pour déployer ces trois éléments, ouvrez à nouveau votre fichierindex.ts
:
nano index.ts
Une fois le fichier ouvert, ajoutez ce code à la fin du fichier:
index.ts
...
const provider = new kubernetes.Provider("do-k8s", { kubeconfig })
const appLabels = { "app": "app-nginx" };
const app = new kubernetes.apps.v1.Deployment("do-app-dep", {
spec: {
selector: { matchLabels: appLabels },
replicas: 5,
template: {
metadata: { labels: appLabels },
spec: {
containers: [{
name: "nginx",
image: "nginx",
}],
},
},
},
}, { provider });
const appService = new kubernetes.core.v1.Service("do-app-svc", {
spec: {
type: "LoadBalancer",
selector: app.spec.template.metadata.labels,
ports: [{ port: 80 }],
},
}, { provider });
export const ingressIp = appService.status.loadBalancer.ingress[0].ip;
Ce code est similaire à la configuration standard de Kubernetes et le comportement des objets et de leurs propriétés est équivalent, à la différence qu’il est écrit en TypeScript avec vos autres déclarations d’infrastructure.
Enregistrez et fermez le fichier après avoir apporté les modifications.
Tout comme avant, exécutezpulumi up
pour prévisualiser puis déployer les modifications:
pulumi up
Après avoir sélectionnéyes
pour continuer, la CLI imprimera des mises à jour détaillées de l'état, y compris des diagnostics concernant la disponibilité des pods, l'allocation d'adresses IP, etc. Cela vous aidera à comprendre pourquoi votre déploiement prend du temps à se terminer ou reste bloqué.
La sortie complète ressemblera à ceci:
OutputUpdating (dev):
Type Name Status
pulumi:pulumi:Stack do-k8s-dev
+ ├─ pulumi:providers:kubernetes do-k8s created
+ ├─ kubernetes:apps:Deployment do-app-dep created
+ └─ kubernetes:core:Service do-app-svc created
Outputs:
+ ingressIp : "157.230.199.202"
Resources:
+ 3 created
2 unchanged
Duration: 2m52s
Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/2
Une fois cette opération terminée, notez que le nombre souhaité de pods est en cours d'exécution:
KUBECONFIG=./kubeconfig.yml kubectl get pods
OutputNAME READY STATUS RESTARTS AGE
do-app-dep-vyf8k78z-758486ff68-5z8hk 1/1 Running 0 1m
do-app-dep-vyf8k78z-758486ff68-8982s 1/1 Running 0 1m
do-app-dep-vyf8k78z-758486ff68-94k7b 1/1 Running 0 1m
do-app-dep-vyf8k78z-758486ff68-cqm4c 1/1 Running 0 1m
do-app-dep-vyf8k78z-758486ff68-lx2d7 1/1 Running 0 1m
De la même manière que le programme exporte le fichierkubeconfig
du cluster, ce programme exporte également l'adresse IP de l'équilibreur de charge résultant du service Kubernetes. Utilisez ceci pourcurl
le point de terminaison et voir qu'il est opérationnel:
curl $(pulumi stack output ingressIp)
À partir de là, vous pouvez facilement modifier et redéployer votre infrastructure d’applications. Par exemple, essayez de changer la lignereplicas: 5
pour direreplicas: 7
, puis réexécutezpulumi up
:
pulumi up
Notez que cela montre simplement ce qui a changé et que la sélection des détails affiche le diff précis:
OutputPreviewing update (dev):
Type Name Plan Info
pulumi:pulumi:Stack do-k8s-dev
~ └─ kubernetes:apps:Deployment do-app-dep update [diff: ~spec]
Resources:
~ 1 to update
4 unchanged
Do you want to perform this update? details
pulumi:pulumi:Stack: (same)
[urn=urn:pulumi:dev::do-k8s::pulumi:pulumi:Stack::do-k8s-dev]
~ kubernetes:apps/v1:Deployment: (update)
[id=default/do-app-dep-vyf8k78z]
[urn=urn:pulumi:dev::do-k8s::kubernetes:apps/v1:Deployment::do-app-dep]
[provider=urn:pulumi:dev::do-k8s::pulumi:providers:kubernetes::do-k8s::80f36105-337f-451f-a191-5835823df9be]
~ spec: {
~ replicas: 5 => 7
}
Vous avez maintenant à la fois un cluster Kubernetes entièrement fonctionnel et une application opérationnelle. Lorsque votre application est opérationnelle, vous pouvez configurer un domaine personnalisé à utiliser avec votre application. La prochaine étape vous guidera dans la configuration du DNS avec Pulumi.
[[step-5 -—- creating-a-dns-domain-optional]] == Étape 5 - Création d'un domaine DNS (facultatif)
Bien que le cluster et l’application Kubernetes soient opérationnels, son adresse dépend des caprices de l’attribution automatique d’adresses IP par votre cluster. Lorsque vous ajustez et redéployez des éléments, cette adresse peut changer. Au cours de cette étape, vous verrez comment attribuer un nom DNS personnalisé à l’adresse IP de l’équilibreur de charge afin qu’elle soit stable, même si vous modifiez ultérieurement votre infrastructure.
[.note] #Note: Pour terminer cette étape, assurez-vous que vous disposez d'un domaine utilisant les serveurs de noms DNS de DigitalOcean,ns1.digitalocean.com
,ns2.digitalocean.com
etns3.digitalocean.com
. Les instructions pour configurer ceci sont disponibles dans la section Prérequis.
#
Pour configurer DNS, ouvrez le fichierindex.ts
et ajoutez le code suivant à la fin du fichier:
index.ts
...
const domain = new digitalocean.Domain("do-domain", {
name: "your_domain",
ipAddress: ingressIp,
});
Ce code crée une nouvelle entrée DNS avec un enregistrement A qui fait référence à l’adresse IP de votre service Kubernetes. Remplacezyour_domain
dans cet extrait de code par le nom de domaine choisi.
Il est courant de vouloir que des sous-domaines supplémentaires, tels quewww
, pointent vers l'application Web. Ceci est facile à réaliser en utilisant un enregistrement DNS DigitalOcean. Pour rendre cet exemple plus intéressant, ajoutez également un enregistrementCNAME
qui pointewww.your_domain.com
versyour_domain.com
:
index.ts
...
const cnameRecord = new digitalocean.DnsRecord("do-domain-cname", {
domain: domain.name,
type: "CNAME",
name: "www",
value: "@",
});
Enregistrez et fermez le fichier après avoir apporté ces modifications.
Enfin, exécutezpulumi up
pour déployer les modifications DNS afin qu'elles pointent vers votre application et votre cluster existants:
OutputUpdating (dev):
Type Name Status
pulumi:pulumi:Stack do-k8s-dev
+ ├─ digitalocean:index:Domain do-domain created
+ └─ digitalocean:index:DnsRecord do-domain-cname created
Resources:
+ 2 created
5 unchanged
Duration: 6s
Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/3
Une fois les modifications DNS propagées, vous pourrez accéder à votre contenu sur votre domaine personnalisé:
curl www.your_domain.com
Vous recevrez une sortie similaire à celle-ci:
Avec cela, vous avez réussi à configurer un nouveau cluster DigitalOcean Kubernetes, à y déployer une application Kubernetes à charge équilibrée et à donner à l'équilibreur de charge de cette application un nom de domaine stable utilisant DigitalOcean DNS, le tout dans 60 lignes de code et unpulumi up
commander.
La prochaine étape vous guidera tout au long de la suppression des ressources si vous n'en avez plus besoin.
[[step-6 -—- remove-the-resources-optional]] == Étape 6 - Suppression des ressources (facultatif)
Avant de terminer le didacticiel, vous souhaiterez peut-être détruire toutes les ressources créées ci-dessus. Cela garantira que vous ne serez pas facturé pour des ressources qui ne sont pas utilisées. Si vous préférez que votre application reste opérationnelle, n'hésitez pas à ignorer cette étape.
Exécutez la commande suivante pour détruire les ressources. Soyez prudent en utilisant ceci, car cela ne peut pas être annulé!
pulumi destroy
Tout comme avec la commandeup
,destroy
affiche un aperçu et une invite avant d'agir:
OutputPreviewing destroy (dev):
Type Name Plan
- pulumi:pulumi:Stack do-k8s-dev delete
- ├─ digitalocean:index:DnsRecord do-domain-cname delete
- ├─ digitalocean:index:Domain do-domain delete
- ├─ kubernetes:core:Service do-app-svc delete
- ├─ kubernetes:apps:Deployment do-app-dep delete
- ├─ pulumi:providers:kubernetes do-k8s delete
- └─ digitalocean:index:KubernetesCluster do-cluster delete
Resources:
- 7 to delete
Do you want to perform this destroy?
yes
> no
details
En supposant que c'est ce que vous voulez, sélectionnezyes
et regardez les suppressions se produire:
OutputDestroying (dev):
Type Name Status
- pulumi:pulumi:Stack do-k8s-dev deleted
- ├─ digitalocean:index:DnsRecord do-domain-cname deleted
- ├─ digitalocean:index:Domain do-domain deleted
- ├─ kubernetes:core:Service do-app-svc deleted
- ├─ kubernetes:apps:Deployment do-app-dep deleted
- ├─ pulumi:providers:kubernetes do-k8s deleted
- └─ digitalocean:index:KubernetesCluster do-cluster deleted
Resources:
- 7 deleted
Duration: 7s
Permalink: https://app.pulumi.com/.../do-k8s/dev/updates/4
À ce stade, rien ne reste: les entrées DNS ont disparu et le cluster Kubernetes, ainsi que l'application qui s'exécute à l'intérieur, ont disparu. Le lien permanent est toujours disponible, vous pouvez donc toujours revenir en arrière et voir l'historique complet des mises à jour pour cette pile. Cela pourrait vous aider à récupérer si la destruction était une erreur, car le service conserve l'historique complet de l'état de toutes les ressources.
Si vous souhaitez détruire votre projet dans son intégralité, supprimez la pile:
pulumi stack rm
Vous recevrez une sortie vous demandant de confirmer la suppression en tapant le nom de la pile:
OutputThis will permanently remove the 'dev' stack!
Please confirm that this is what you'd like to do by typing ("dev"):
Contrairement à la commande destroy, qui supprime les ressources d’infrastructure cloud, la suppression d’une pile efface complètement l’historique complet de votre pile de la compétence de Pulumi.
Conclusion
Dans ce didacticiel, vous avez déployé des ressources d'infrastructure DigitalOcean - un cluster Kubernetes et un domaine DNS avec des enregistrements A et CNAME - en plus de la configuration d'application Kubernetes qui utilise ce cluster. Vous avez utilisé l'infrastructure-as-code écrite dans un langage de programmation familier, TypeScript, qui fonctionne avec les éditeurs, les outils et les bibliothèques existants et exploite les communautés et les packages existants. Vous avez tout fait en utilisant un seul flux de travail en ligne de commande pour effectuer des déploiements couvrant votre application et votre infrastructure.
A partir de là, vous pouvez prendre un certain nombre de prochaines étapes:
-
Découvrez l'ensemble complet des ressources DigitalOcean prises en charge par Pulumi.
-
Déclenchez automatiquement les déploiements avec les intégrations de flux de travail CI / CD et Git.
-
Make certain elements of your program configurable comme lesexample does, àfacilitate larger projects and multi-stack approaches (tels que dev, test, staging, production).
L'échantillon complet de ce didacticiel estavailable on GitHub. Pour plus de détails sur l'utilisation de l'infrastructure en tant que code Pulumi dans vos propres projets aujourd'hui, consultez les guidesPulumi Documentation,Tutorials ouGetting Started. Pulumi est open source et libre d'utilisation.