Calendrier de l'Avent terraform 2019 Jour 6: christamas_tree:.
Cet article concerne l'automatisation Terraform dans un environnement Oracle Cloud.
L'infrastructure cloud utilisée sera Oracle Cloud, mais la manière de base d'écrire des fichiers tf ne changera pas, de sorte que l'idée générale peut également être appliquée à d'autres clouds.
Dans cet article, nous allons commencer par la gestion déclarative de la configuration, expliquer les grandes lignes de Terraform, son utilisation de base et déployer l'environnement suivant (*). Profitez de la puissance de Terraform!
(*) Le fichier tf décrit dans cet article est disponible sur GitHub.
Avant d'apprendre Terraform, connaissons ** la gestion déclarative de la configuration ** et ** l'objectif de l'outil de gestion de la configuration **. Vous pouvez maximiser la valeur de Terraform!
** Cloud Native ** (*) est une approche qui fait abstraction des ressources d'infrastructure conventionnelles et développe des applications dans un environnement cloud.
De plus, étant donné que le cloud natif est centré sur l'infrastructure cloud, il a une forte affinité avec les applications qui sont divisées en composants les plus petits tels que la technologie de déguisement de type conteneur et les micro services. Puisqu'il est possible de répondre de manière flexible à la méthode de développement d'un système avec un cycle court tel qu'une version agile, on peut s'attendre à une version rapide.
Par exemple, dans le développement d'une cascade dans un environnement sur site traditionnel, il existe les phases suivantes pour les ressources d'infrastructure:
--Déterminer les ressources du serveur par estimation des performances de la définition des exigences (exigence non fonctionnelle)
Ensuite, lorsque vous entrez dans la phase d'exploitation après la publication et que vous effectuez la gestion des services selon ITIL, chaque processus de gestion de la configuration, de gestion des changements et de gestion des versions se produit.
Cependant, en raison de la démocratisation du cloud et de la pénétration de la technologie de virtualisation de conteneurs, les mots à la mode de DevOps et du cloud natif sont nés, et en tant que technologies qui prennent en charge le cycle de vie de la gestion de la configuration depuis la construction, des outils de gestion de la configuration tels que Puppet et Chef et l'orchestration tels que Kubernetes Avec l'attention des outils de rationnement, l'approche du système a évolué vers une procédure déclarative.
Désormais, le concept d'infrastructure en cloud natif peut être considéré comme une architecture cloud native basée sur la ** gestion déclarative de la configuration **.
En supposant une gestion de configuration déclarative, la conception opérationnelle peut être prise en considération lors de la conception de l'architecture du système. Dans le passé, l'automatisation pouvait être envisagée au moment de la conception, même pour des problèmes apparus après le début de l'exploitation. Cela facilite également l'évolutivité.
(*) Le mot cloud native n'est pas strictement défini comme le sens du mot, comme l'intelligence artificielle.
Considérez l'objectif de l'outil de gestion de la configuration.
** Du point de vue de DevOps, ce n'est pas le but d'introduire des outils de gestion de configuration, mais dans quelle mesure le processus de développement peut être optimisé en utilisant les moyens des outils de gestion de configuration. ** **
Auparavant, j'ai écrit dans Qu'est-ce qu'Ansible? Objectif de l'outil de gestion de la configuration - Comprendre le moyen le plus rapide d'introduire Ansible, mais l'objectif de l'introduction de l'outil de gestion de la configuration Vous pouvez voir ce que vous voulez faire en clarifiant.
Par conséquent, si vous ne clarifiez pas l'objectif de l'outil de gestion de la configuration et que vous ne comprenez pas et ne prévoyez pas les avantages et le flux post-opération, vous ne pourrez pas maximiser les avantages.
Par conséquent, avec Terraform, vous pouvez automatiser la création auparavant manuelle de ressources d'infrastructure cloud. De plus, si vous le combinez avec Ansible, etc., vous pouvez travailler efficacement avec la configuration du système d'exploitation et de MW en même temps.
** En conséquence, en introduisant un outil de gestion de la configuration tel que Terraform, vous pouvez réduire considérablement le travail chronophage et consacrer ce temps à d'autres problèmes importants. ** **
Aussi, du point de vue de l'égalité, ce sera la même chose, peu importe qui le fait, donc nous éviterons les erreurs opérationnelles et maintiendrons la qualité. Cela fonctionne très bien non seulement dans la phase de développement, mais également dans la phase d'exploitation.
Dans cet article, nous utiliserons Terraform et cloud-init pour créer des ressources pour l'infrastructure cloud et configurer initialement le système d'exploitation et le MW.
Terraform est l'un des outils de gestion de la configuration pour gérer les ressources de l'infrastructure cloud.
Il fournit un processus permettant d'automatiser le provisionnement requis pour le développement d'applications modernes telles que ** DevOps ** et ** Infrastructure as Code **.
L'utilisation de Terraform est très simple. Vous pouvez créer une infrastructure cloud simplement en décrivant les informations sur les ressources telles que les instances et les réseaux dans un fichier de définition appelé fichier tf et en exécutant la commande terraform.
En tant qu'image, il est très similaire aux appareils de cuisine populaires "Slow Cooker" aux États-Unis. Le processus de réglage des ingrédients et d'appuyer sur l'interrupteur pour terminer le plat est exactement le même.
Mais ce n'est pas une ** solution miracle **.
** Après avoir essayé différentes choses avec Terraform, je veux le faire aussi, mais certaines choses ne peuvent pas être faites en raison des spécifications du fournisseur de cloud. ** **
Lors du déploiement de Terraform, il est conseillé de faire beaucoup de validation pour clarifier ce que vous pouvez et ne pouvez pas faire.
Pour créer avec Terraform dans l'environnement Oracle Cloud, créez un utilisateur et préparez les informations d'identification nécessaires. Après cela, installez Terraform et préparez le fichier tf nécessaire à l'exécution de Terraform.
Les prérequis pour un environnement Oracle Cloud sont répertoriés ci-dessous.
Dans cet article, nous utiliserons Mac comme exemple.
.bashrc
etc. Voici un exemple de passage du chemin sous l'application.export PATH=$PATH:/Applications/
Après avoir transmis le chemin, exécutez la commande suivante, et si les informations de version sont affichées, le chemin est transmis.
# terraform -v
Terraform v0.12.7
Your version of Terraform is out of date! The latest version
is 0.12.13. You can update by downloading from www.terraform.io/downloads.html
(*) Ce qui précède est affiché car la version de Terraform que vous utilisez est ancienne. Ne s'affiche pas si vous utilisez une version plus récente de Terraform.
Il est automatiquement téléchargé lorsque terraform init
, qui sera décrit plus loin, est exécuté, donc aucun téléchargement séparé n'est requis.
Je vais vous expliquer le fichier tf.
Déplacez-vous d'abord vers n'importe quel répertoire de travail. Dans cet article, la structure de répertoires est la suivante et le répertoire actuel est le répertoire oci.
.
|-- common
| |-- userdata
| |-- cloud-init1.tpl
| |-- cloud-init2.tpl
| |-- compute.tf
| |-- env-vars
| |-- lb.tf
| |-- network.tf
| |-- provider.tf
| |-- securitylist.tf
|-- oci_api_key.pem
|-- oci_api_key_public.pem
`-- ssh
|-- id_rsa
|-- id_rsa.pub
--Diverses explications sur les fichiers
nom de fichier | rôle |
---|---|
cloud-init1.tpl | Script de construction initiale pour le serveur Web |
cloud-init2.tpl | Script de construction initiale pour le serveur de base de données |
compute.tf | Fichier d'instance tf |
env-vars | Fichier tf des variables utilisées par le fournisseur |
lb.tf | Fichier tf de l'équilibreur de charge |
network.tf | Fichier tf réseau |
provider.tf | Fichier tf du fournisseur |
securitylist.tf | Fichier tf de la liste de sécurité |
oci_api_key.pem | Clé privée API |
oci_api_key_public.pem | Clé publique API |
id_rsa | Clé privée SSH |
id_rsa.pub | Clé publique SSH |
** Les points lors de la création d'un fichier tf sont décrits ci-dessous. ** **
=
, donc si vous voulez l'aligner, décidez d'une règle telle que l'aligner et décrivez-la d'une manière facile à comprendre.
--Il y a des symboles inutilisables tels que des barres inférieures dans le nom de la ressourceDécrit le fichier tf utilisé dans cet article. (*)
(*) Certaines valeurs sont des informations d'identification, donc x est utilisé comme exemple.
### Authentication details
export TF_VAR_tenancy_ocid=ocid1.tenancy.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export TF_VAR_user_ocid=ocid1.user.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export TF_VAR_fingerprint=12:34:56:78:90:ab:cd:ef:12:34:56:78:90:ab:cd:ef
export TF_VAR_private_key_path=/oci/oci_api_key.pem
export TF_VAR_private_key_password=xxxxxxxx
### Region
export TF_VAR_region=ap-tokyo-1
### Compartment
export TF_VAR_compartment_ocid=ocid1.compartment.oc1..aaaaaaaaxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
### Public/private keys used on the instance
export TF_VAR_ssh_public_key=$(cat /oci/ssh/id_rsa.pub)
export TF_VAR_ssh_private_key=$(cat /oci/ssh/id_rsa)
(*) Private_key_password
n'est pas requis si vous ne définissez pas de phrase de passe pour la clé privée de l'API.
# Variable
variable "tenancy_ocid" {}
variable "user_ocid" {}
variable "fingerprint" {}
variable "private_key_path" {}
variable "private_key_password" {}
variable "region" {}
variable "compartment_ocid" {}
variable "ssh_private_key" {}
variable "ssh_public_key" {}
# Configure the Oracle Cloud Infrastructure provider with an API Key
provider "oci" {
tenancy_ocid = "${var.tenancy_ocid}"
user_ocid = "${var.user_ocid}"
fingerprint = "${var.fingerprint}"
private_key_path = "${var.private_key_path}"
private_key_password = "${var.private_key_password}"
region = "${var.region}"
}
# Virtual Cloud Network
## vcn1
resource "oci_core_virtual_network" "vcn1" {
display_name = "vcn1"
compartment_id = "${var.compartment_ocid}"
cidr_block = "10.0.0.0/16"
dns_label = "vcn1"
}
## vcn2
resource "oci_core_virtual_network" "vcn2" {
display_name = "vcn2"
compartment_id = "${var.compartment_ocid}"
cidr_block = "192.168.0.0/16"
dns_label = "vcn2"
}
# Subnet
## Subnet LB
resource "oci_core_subnet" "LB_Segment" {
display_name = "Environnement de développement_Segment LB"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
cidr_block = "10.0.0.0/24"
route_table_id = "${oci_core_default_route_table.default-route-table1.id}"
security_list_ids = ["${oci_core_security_list.LB_securitylist.id}"]
}
## Subnet Web
resource "oci_core_subnet" "Web_Segment" {
display_name = "Environnement de développement_Segment WEB"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
cidr_block = "10.0.1.0/24"
route_table_id = "${oci_core_default_route_table.default-route-table1.id}"
security_list_ids = ["${oci_core_security_list.Web_securitylist.id}"]
}
## Subnet DB
resource "oci_core_subnet" "DB_Segment" {
display_name = "Environnement de développement_Segment DB"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
cidr_block = "10.0.2.0/24"
route_table_id = "${oci_core_route_table.nat-route-table.id}"
prohibit_public_ip_on_vnic = "true"
security_list_ids = ["${oci_core_security_list.DB_securitylist.id}"]
}
## Subnet Operation
resource "oci_core_subnet" "Ope_Segment" {
display_name = "Environnement de développement_Segment d'investissement"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn2.id}"
cidr_block = "192.168.1.0/24"
route_table_id = "${oci_core_default_route_table.default-route-table2.id}"
security_list_ids = ["${oci_core_security_list.Ope_securitylist.id}"]
}
# Route Table
## default-route-table1
resource "oci_core_default_route_table" "default-route-table1" {
manage_default_resource_id = "${oci_core_virtual_network.vcn1.default_route_table_id}"
route_rules {
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
network_entity_id = "${oci_core_internet_gateway.internet-gateway1.id}"
}
}
## nat-route-table
resource "oci_core_route_table" "nat-route-table" {
display_name = "nat-route-table"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
route_rules {
destination = "0.0.0.0/0"
network_entity_id = "${oci_core_nat_gateway.nat-gateway.id}"
}
}
## default-route-table2
resource "oci_core_default_route_table" "default-route-table2" {
manage_default_resource_id = "${oci_core_virtual_network.vcn2.default_route_table_id}"
route_rules {
destination = "0.0.0.0/0"
destination_type = "CIDR_BLOCK"
network_entity_id = "${oci_core_internet_gateway.internet-gateway2.id}"
}
}
# Internet Gateway
## internet-gateway1
resource "oci_core_internet_gateway" "internet-gateway1" {
display_name = "internet-gateway1"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
}
## internet-gateway2
resource "oci_core_internet_gateway" "internet-gateway2" {
display_name = "internet-gateway2"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn2.id}"
}
# Nat-Gateway
resource "oci_core_nat_gateway" "nat-gateway" {
display_name = "nat-gateway"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
}
(*) Si vous ne souhaitez pas autoriser les adresses IP publiques pour le sous-réseau, décrivez prohibit_public_ip_on_vnic =" true "
.
/* Load Balancer */
resource "oci_load_balancer" "load-balancer" {
shape = "100Mbps"
compartment_id = "${var.compartment_ocid}"
subnet_ids = [
"${oci_core_subnet.LB_Segment.id}",
]
display_name = "load-balancer"
}
resource "oci_load_balancer_backend_set" "lb-bes1" {
name = "lb-bes1"
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
policy = "ROUND_ROBIN"
health_checker {
port = "80"
protocol = "HTTP"
response_body_regex = ".*"
url_path = "/"
}
}
resource "oci_load_balancer_certificate" "lb-cert1" {
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
ca_certificate = "-----BEGIN CERTIFICATE-----\nMIIC9jCCAd4CCQD2rPUVJETHGzANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxDzANBgNVBAoMBk9yYWNs\nZTAeFw0xOTAxMTcyMjU4MDVaFw0yMTAxMTYyMjU4MDVaMD0xCzAJBgNVBAYTAlVT\nMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwGT3JhY2xl\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA30+wt7OlUB/YpmWbTRkx\nnLG0lKWiV+oupNKj8luXmC5jvOFTUejt1pQhpA47nCqywlOAfk2N8hJWTyJZUmKU\n+DWVV2So2B/obYxpiiyWF2tcF/cYi1kBYeAIu5JkVFwDe4ITK/oQUFEhIn3Qg/oC\nMQ2985/MTdCXONgnbmePU64GrJwfvOeJcQB3VIL1BBfISj4pPw5708qTRv5MJBOO\njLKRM68KXC5us4879IrSA77NQr1KwjGnQlykyCgGvvgwgrUTd5c/dH8EKrZVcFi6\nytM66P/1CTpk1YpbI4gqiG0HBbuXG4JRIjyzW4GT4JXeSjgvrkIYL8k/M4Az1WEc\n2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAuI53m8Va6EafDi6GQdQrzNNQFCAVQ\nxIABAB0uaSYCs3H+pqTktHzOrOluSUEogXRl0UU5/OuvxAz4idA4cfBdId4i7AcY\nqZsBjA/xqH/rxR3pcgfaGyxQzrUsJFf0ZwnzqYJs7fUvuatHJYi/cRBxrKR2+4Oj\nlUbb9TSmezlzHK5CaD5XzN+lZqbsSvN3OQbOryJCbtjZVQFGZ1SmL6OLrwpbBKuP\nn2ob+gaP57YSzO3zk1NDXMlQPHRsdSOqocyKx8y+7J0g6MqPvBzIe+wI3QW85MQY\nj1/IHmj84LNGp7pHCyiYx/oI+00gRch04H2pJv0TP3sAQ37gplBwDrUo\n-----END CERTIFICATE-----"
certificate_name = "certificate1"
private_key = "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA30+wt7OlUB/YpmWbTRkxnLG0lKWiV+oupNKj8luXmC5jvOFT\nUejt1pQhpA47nCqywlOAfk2N8hJWTyJZUmKU+DWVV2So2B/obYxpiiyWF2tcF/cY\n\ni1kBYeAIu5JkVFwDe4ITK/oQUFEhIn3Qg/oCMQ2985/MTdCXONgnbmePU64GrJwf\nvOeJcQB3VIL1BBfISj4pPw5708qTRv5MJBOOjLKRM68KXC5us4879IrSA77NQr1K\nwjGnQlykyCgGvvgwgrUTd5c/dH8EKrZVcFi6ytM66P/1CTpk1YpbI4gqiG0HBbuX\nG4JRIjyzW4GT4JXeSjgvrkIYL8k/M4Az1WEc2wIDAQABAoIBAGQznukfG/uS/qTT\njNcQifl0p8HXfLwUIa/lsJkMTj6D+k8DkF59tVMGjv3NQSQ26JVX4J1L8XiAj+fc\nUtYr1Ap4CLX5PeYUkzesvKK6lPKXQvCh+Ip2eq9PVrvL2WcdDpb5695cy7suXD7c\n05aUtS0LrINH3eXAxkpEe5UHtQFni5YLrCLEXd+SSA3OKdCB+23HRELc1iCTvqjK\n5AtR916uHTBhtREHRMvWIdu4InRUsedlJhaJOLJ8G8r64JUtfm3wLUK1U8HFOsd0\nLAx9ZURU6cXl4osTWiy1vigGaM8Xuish2HkOLNYZADDUiDBB3SshmW5IDAJ5XTn5\nqVrszRECgYEA79j1y+WLTyV7yz7XkWk3OqoQXG4b2JfKItJI1M95UwllzQ8U/krM\n+QZjP3NTtB9i1YoHyaEfic103hV9Fkgz8jvKS5ocLGJulpN4CgqbHN6v9EJ3dqTk\no6X8mpx2eP2E0ngRekFyC/OCp0Zhe2KR9PXhijMa5eB2LTeCMIS/tzkCgYEA7lmk\nIdVjcpfqY7UFJ2R8zqPJHOne2+llrl9vzo6N5kx4DzAg7MP6XO9MekOvfmD1X1Lm\nFckXWFEF+0TlN5YvCTR/+OmVufYM3xp4GBT8RZdLFbyI4+xpAAeSC4SeM0ZkC9Jt\nrKqCS24+Kqy/+qSqtkxiPLQrXSdCSfCUlmn0ALMCgYBB7SLy3q+CG82BOk7Km18g\n8un4XhOtX1uiYqa+SCETH/wpd0HP/AOHV6gkIrEZS59BDuXBGFaw7BZ5jPKLE2Gj\n7adXTI797Dh1jydpqyyjrNo0i6iGpiBqkw9x+Bvged7ucy5qql6MxmxdSk01Owzf\nhk5uTEnScfZJy34vk+2WkQKBgBXx5uy+iuN4HTqE5i6UT/FunwusdLpmqNf/LXol\nIed8TumHEuD5wklgNvhi1vuZzb2zEkAbPa0B+L0DwN73UulUDhxK1WBDyTeZZklB\nVWDK5zzfGPNzRs+b4tRwp2gtKPT1sOde45QyWELxmNNo6dbS/ZB9Pijbfnz0S5n1\ns2OFAoGBAJUohI1+d2hKlkSUzpCorQarDe8lFVEbGMu0kX0JNDI7QU+H8vDp9NOl\nGqLm3sCVBYypT8sWfchgZpcVaLRLQCQtWy4+CbMN6DT3j/uBWeDpayU5Gvqt0/no\nvwqbG6b0NEYLRPLEdsS/c8TV9mMlvb0EW+GXfmkpTrTNt3hyXniu\n-----END RSA PRIVATE KEY-----"
public_certificate = "-----BEGIN CERTIFICATE-----\nMIIC9jCCAd4CCQD2rPUVJETHGzANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1NlYXR0bGUxDzANBgNVBAoMBk9yYWNs\nZTAeFw0xOTAxMTcyMjU4MDVaFw0yMTAxMTYyMjU4MDVaMD0xCzAJBgNVBAYTAlVT\nMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHU2VhdHRsZTEPMA0GA1UECgwGT3JhY2xl\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA30+wt7OlUB/YpmWbTRkx\nnLG0lKWiV+oupNKj8luXmC5jvOFTUejt1pQhpA47nCqywlOAfk2N8hJWTyJZUmKU\n+DWVV2So2B/obYxpiiyWF2tcF/cYi1kBYeAIu5JkVFwDe4ITK/oQUFEhIn3Qg/oC\nMQ2985/MTdCXONgnbmePU64GrJwfvOeJcQB3VIL1BBfISj4pPw5708qTRv5MJBOO\njLKRM68KXC5us4879IrSA77NQr1KwjGnQlykyCgGvvgwgrUTd5c/dH8EKrZVcFi6\nytM66P/1CTpk1YpbI4gqiG0HBbuXG4JRIjyzW4GT4JXeSjgvrkIYL8k/M4Az1WEc\n2wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAuI53m8Va6EafDi6GQdQrzNNQFCAVQ\nxIABAB0uaSYCs3H+pqTktHzOrOluSUEogXRl0UU5/OuvxAz4idA4cfBdId4i7AcY\nqZsBjA/xqH/rxR3pcgfaGyxQzrUsJFf0ZwnzqYJs7fUvuatHJYi/cRBxrKR2+4Oj\nlUbb9TSmezlzHK5CaD5XzN+lZqbsSvN3OQbOryJCbtjZVQFGZ1SmL6OLrwpbBKuP\nn2ob+gaP57YSzO3zk1NDXMlQPHRsdSOqocyKx8y+7J0g6MqPvBzIe+wI3QW85MQY\nj1/IHmj84LNGp7pHCyiYx/oI+00gRch04H2pJv0TP3sAQ37gplBwDrUo\n-----END CERTIFICATE-----"
lifecycle {
create_before_destroy = true
}
}
resource "oci_load_balancer_path_route_set" "test_path_route_set" {
#Required
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
name = "pr-set1"
path_routes {
#Required
backend_set_name = "${oci_load_balancer_backend_set.lb-bes1.name}"
path = "/test"
path_match_type {
#Required
match_type = "EXACT_MATCH"
}
}
}
resource "oci_load_balancer_hostname" "test_hostname1" {
#Required
hostname = "app.example.com"
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
name = "hostname1"
}
resource "oci_load_balancer_listener" "lb-listener1" {
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
name = "http"
default_backend_set_name = "${oci_load_balancer_backend_set.lb-bes1.name}"
hostname_names = ["${oci_load_balancer_hostname.test_hostname1.name}"]
port = 80
protocol = "HTTP"
connection_configuration {
idle_timeout_in_seconds = "2"
}
}
resource "oci_load_balancer_listener" "lb-listener2" {
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
name = "https"
default_backend_set_name = "${oci_load_balancer_backend_set.lb-bes1.name}"
port = 443
protocol = "HTTP"
ssl_configuration {
certificate_name = "${oci_load_balancer_certificate.lb-cert1.certificate_name}"
verify_peer_certificate = false
}
}
resource "oci_load_balancer_backend" "lb-be1" {
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
backendset_name = "${oci_load_balancer_backend_set.lb-bes1.name}"
ip_address = "${var.ip_address3}"
port = 80
backup = false
drain = false
offline = false
weight = 1
}
resource "oci_load_balancer_backend" "lb-be2" {
load_balancer_id = "${oci_load_balancer.load-balancer.id}"
backendset_name = "${oci_load_balancer_backend_set.lb-bes1.name}"
ip_address = "${var.ip_address4}"
port = 80
backup = false
drain = false
offline = false
weight = 1
}
output "lb_public_ip" {
value = ["${oci_load_balancer.load-balancer.ip_address_details}"]
}
(*) Si vous décrivez la sortie, vous pouvez afficher la valeur spécifiée par la sortie après avoir créé la ressource.
# Security list
## LB
resource "oci_core_security_list" "LB_securitylist" {
display_name = "Environnement de développement_Segment LB"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
ingress_security_rules {
source = "0.0.0.0/0"
protocol = "6"
tcp_options {
min = 443
max = 443
}
}
egress_security_rules {
destination = "0.0.0.0/0"
protocol = "ALL"
}
}
## Web
resource "oci_core_security_list" "Web_securitylist" {
display_name = "Environnement de développement_Segment Web"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
ingress_security_rules {
source = "10.0.0.0/24"
protocol = "6"
tcp_options {
min = 80
max = 80
}
}
egress_security_rules {
destination = "0.0.0.0/0"
protocol = "ALL"
}
}
## DB
resource "oci_core_security_list" "DB_securitylist" {
display_name = "Environnement de développement_Segment DB"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn1.id}"
ingress_security_rules {
source = "10.0.1.0/24"
protocol = "6"
tcp_options {
min = 5432
max = 5432
}
}
egress_security_rules {
destination = "0.0.0.0/0"
protocol = "ALL"
}
}
## Security list Ope
resource "oci_core_security_list" "Ope_securitylist" {
display_name = "Environnement de développement_Segment d'investissement"
compartment_id = "${var.compartment_ocid}"
vcn_id = "${oci_core_virtual_network.vcn2.id}"
ingress_security_rules {
source = "192.168.1.0/24"
protocol = "1"
}
ingress_security_rules {
source = "x.x.x.x/32"
protocol = "6"
tcp_options {
min = 22
max = 22
}
}
ingress_security_rules {
source = "192.168.1.0/24"
protocol = "6"
tcp_options {
min = 22
max = 22
}
}
egress_security_rules {
destination = "0.0.0.0/0"
protocol = "ALL"
}
}
(*) Source =" x.x.x.x / 32 "
est décrit comme une restriction SSH pour les adresses IP publiques.
# Variable
variable "ImageOS" {
default = "Oracle Linux"
}
variable "ImageOSVersion" {
default = "7.7"
}
variable "instance_shape" {
default = "VM.Standard.E2.1"
}
variable "fault_domain" {
default = "FAULT-DOMAIN-1"
}
variable "ip_address1" {
default = "192.168.1.2"
}
variable "ip_address2" {
default = "192.168.1.3"
}
variable "ip_address3" {
default = "10.0.1.2"
}
variable "ip_address4" {
default = "10.0.1.3"
}
variable "ip_address5" {
default = "192.168.1.4"
}
variable "ip_address6" {
default = "10.0.2.2"
}
variable "ip_address7" {
default = "192.168.1.5"
}
# Gets a list of Availability Domains
data "oci_identity_availability_domains" "ADs" {
compartment_id = "${var.tenancy_ocid}"
}
# Gets a list of all Oracle Linux 7.7 images that support a given Instance shape
data "oci_core_images" "instance" {
compartment_id = "${var.tenancy_ocid}"
operating_system = "${var.ImageOS}"
operating_system_version = "${var.ImageOSVersion}"
shape = "${var.instance_shape}"
}
# Instance
## Compute Web-Server#1
resource "oci_core_instance" "instance1" {
source_details {
source_type = "image"
source_id = "${lookup(data.oci_core_images.instance.images[0], "id")}"
}
display_name = "Web-Server#1"
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
shape = "${var.instance_shape}"
compartment_id = "${var.compartment_ocid}"
create_vnic_details {
subnet_id = "${oci_core_subnet.Ope_Segment.id}"
assign_public_ip = "true"
private_ip = "${var.ip_address1}"
}
metadata = {
ssh_authorized_keys = "${var.ssh_public_key}"
user_data = "${base64encode(file("./userdata/cloud-init1.tpl"))}"
}
fault_domain = "${var.fault_domain}"
provisioner "remote-exec" {
connection {
host = "${oci_core_instance.instance1.public_ip}"
type = "ssh"
user = "opc"
agent = "true"
timeout = "3m"
}
inline = [
"crontab -l | { cat; echo \"@reboot sudo /usr/local/bin/secondary_vnic_all_configure.sh -c\"; } | crontab -"
]
}
}
### SecondaryVNIC Web-Server#1
resource "oci_core_vnic_attachment" "Web1_secondary_vnic_attachment" {
create_vnic_details {
display_name = "SecondaryVNIC"
subnet_id = "${oci_core_subnet.Web_Segment.id}"
assign_public_ip = "true"
private_ip = "${var.ip_address3}"
skip_source_dest_check = "false"
}
instance_id = "${oci_core_instance.instance1.id}"
}
## Compute Web-Server#2
resource "oci_core_instance" "instance2" {
source_details {
source_type = "image"
source_id = "${lookup(data.oci_core_images.instance.images[0], "id")}"
}
display_name = "Web-Server#2"
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
shape = "${var.instance_shape}"
compartment_id = "${var.compartment_ocid}"
create_vnic_details {
subnet_id = "${oci_core_subnet.Ope_Segment.id}"
assign_public_ip = "true"
private_ip = "${var.ip_address2}"
}
metadata = {
ssh_authorized_keys = "${var.ssh_public_key}"
user_data = "${base64encode(file("./userdata/cloud-init1.tpl"))}"
}
fault_domain = "${var.fault_domain}"
provisioner "remote-exec" {
connection {
host = "${oci_core_instance.instance2.public_ip}"
type = "ssh"
user = "opc"
agent = "true"
timeout = "3m"
}
inline = [
"crontab -l | { cat; echo \"@reboot sudo /usr/local/bin/secondary_vnic_all_configure.sh -c\"; } | crontab -"
]
}
}
### SecondaryVNIC Web-Server#2
resource "oci_core_vnic_attachment" "Web2_secondary_vnic_attachment" {
create_vnic_details {
display_name = "SecondaryVNIC"
subnet_id = "${oci_core_subnet.Web_Segment.id}"
assign_public_ip = "true"
private_ip = "${var.ip_address4}"
skip_source_dest_check = "false"
}
instance_id = "${oci_core_instance.instance2.id}"
}
## Compute DB-Server
resource "oci_core_instance" "instance3" {
source_details {
source_type = "image"
source_id = "${lookup(data.oci_core_images.instance.images[0], "id")}"
}
display_name = "DB-Server"
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
shape = "${var.instance_shape}"
compartment_id = "${var.compartment_ocid}"
create_vnic_details {
subnet_id = "${oci_core_subnet.Ope_Segment.id}"
private_ip = "${var.ip_address5}"
}
metadata = {
ssh_authorized_keys = "${var.ssh_public_key}"
user_data = "${base64encode(file("./userdata/cloud-init2.tpl"))}"
}
fault_domain = "${var.fault_domain}"
provisioner "remote-exec" {
connection {
host = "${oci_core_instance.instance3.public_ip}"
type = "ssh"
user = "opc"
agent = "true"
timeout = "3m"
}
inline = [
"crontab -l | { cat; echo \"@reboot sudo /usr/local/bin/secondary_vnic_all_configure.sh -c\"; } | crontab -"
]
}
}
### SecondaryVNIC DB-Server
resource "oci_core_vnic_attachment" "DB_secondary_vnic_attachment" {
create_vnic_details {
display_name = "SecondaryVNIC"
subnet_id = "${oci_core_subnet.DB_Segment.id}"
assign_public_ip = false
private_ip = "${var.ip_address6}"
skip_source_dest_check = "false"
}
instance_id = "${oci_core_instance.instance3.id}"
}
## Compute Operation-Server
resource "oci_core_instance" "instance4" {
source_details {
source_type = "image"
source_id = "${lookup(data.oci_core_images.instance.images[0], "id")}"
}
display_name = " Operation-Server"
availability_domain = "${lookup(data.oci_identity_availability_domains.ADs.availability_domains[0], "name")}"
shape = "${var.instance_shape}"
compartment_id = "${var.compartment_ocid}"
create_vnic_details {
subnet_id = "${oci_core_subnet.Ope_Segment.id}"
private_ip = "${var.ip_address7}"
}
metadata = {
ssh_authorized_keys = "${var.ssh_public_key}"
user_data = "${base64encode(file("./userdata/cloud-init1.tpl"))}"
}
fault_domain = "${var.fault_domain}"
provisioner "remote-exec" {
connection {
host = "${oci_core_instance.instance3.public_ip}"
type = "ssh"
user = "opc"
agent = "true"
timeout = "3m"
}
inline = [
"crontab -l | { cat; echo \"@reboot sudo /usr/local/bin/secondary_vnic_all_configure.sh -c\"; } | crontab -"
]
}
}
#cloud-config
runcmd:
# download the secondary vnic script
- wget -O /usr/local/bin/secondary_vnic_all_configure.sh https://docs.cloud.oracle.com/iaas/Content/Resources/Assets/secondary_vnic_all_configure.sh
- chmod +x /usr/local/bin/secondary_vnic_all_configure.sh
- sleep 60
- /usr/local/bin/secondary_vnic_all_configure.sh -c
- yum update -y
- echo "Hello World. The time is now $(date -R)!" | tee /root/output.txt
- echo '################### webserver userdata begins #####################'
- touch ~opc/userdata.`date +%s`.start
# echo '########## yum update all ###############'
# yum update -y
- echo '########## basic webserver ##############'
- yum install -y httpd
- systemctl enable httpd.service
- systemctl start httpd.service
- echo '<html><head></head><body><pre><code>' > /var/www/html/index.html
- hostname >> /var/www/html/index.html
- echo '' >> /var/www/html/index.html
- cat /etc/os-release >> /var/www/html/index.html
- echo '</code></pre></body></html>' >> /var/www/html/index.html
- firewall-offline-cmd --add-service=http
- systemctl enable firewalld
- systemctl restart firewalld
- touch ~opc/userdata.`date +%s`.finish
- echo '################### webserver userdata ends #######################'
#cloud-config
runcmd:
# download the secondary vnic script
- wget -O /usr/local/bin/secondary_vnic_all_configure.sh https://docs.cloud.oracle.com/iaas/Content/Resources/Assets/secondary_vnic_all_configure.sh
- chmod +x /usr/local/bin/secondary_vnic_all_configure.sh
- sleep 60
- /usr/local/bin/secondary_vnic_all_configure.sh -c
- echo 'PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin' > /var/spool/cron/root
- echo '@reboot /usr/local/bin/secondary_vnic_all_configure.sh -c' >> /var/spool/cron/root
#Paramètres de port utilisés par Postgresql
- setenforce 0
- firewall-cmd --permanent --add-port=5432/tcp
- firewall-cmd --permanent --add-port=5432/udp
- firewall-cmd --reload
#Installation des packages requis
- yum install -y gcc
- yum install -y readline-devel
- yum install -y zlib-devel
#Installez PostgreSQL
- cd /usr/local/src/
- wget https://ftp.postgresql.org/pub/source/v11.3/postgresql-11.3.tar.gz
- tar xvfz postgresql-11.3.tar.gz
- cd postgresql-11.3/
#compiler
- ./configure
- make
- make install
#Créer un script de démarrage
- cp /usr/local/src/postgresql-11.3/contrib/start-scripts/linux /etc/init.d/postgres
- chmod 755 /etc/init.d/postgres
- chkconfig --add postgres
- chkconfig --list | grep postgres
#Utilisateur Postgres créé
- adduser postgres
Tout d'abord, effectuez les travaux préparatoires suivants.
$ source env-vars
--Confirmation des variables d'environnement
$ env
--Enregistrement de la clé privée SSH (*)
$ ssh-add /oci/ssh/id_rsa
(*) Terraform ne prend pas en charge les clés SSH protégées par mot de passe. Ceci est évité en enregistrant la clé ssh dans l'agent SSH. Non requis si vous n'avez pas défini de phrase de passe pour votre clé privée SSH.
Après avoir terminé les travaux préparatoires, il est enfin temps de construire Terraform. Les travaux de construction de Terraform sont les 3 prochaines étapes!
terraform dedans
plan terraform
terraform apply
Regardons-les dans l'ordre.
terraform init
terraform init
initialise le répertoire de travail qui contient le fichier de configuration Terraform. Si aucun argument n'est spécifié, la configuration actuelle du répertoire de travail sera initialisée. Lors de l'initialisation, Terraform recherche dans la configuration des références directes et indirectes au fournisseur et charge les plugins requis.
# terraform init
Initializing the backend...
Initializing provider plugins...
The following providers do not have any version constraints in configuration,
so the latest version was installed.
To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.
* provider.oci: version = "~> 3.40"
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
terraform plan
terraform plan
est utilisé pour créer un plan d'exécution. Cela ne se reflète pas simplement en exécutant cette commande. Il est utilisé pour tester s'il fonctionne comme prévu sans changer les ressources ou l'état réels. Vous pouvez également utiliser l'argument optionnel -out
pour enregistrer le plan généré dans un fichier pour une exécution ultérieure. Notez que s'il y a une erreur dans le fichier tf, elle sera détectée, mais même si terraform plan
réussit, il peut échouer avec terraform apply
, alors soyez prudent.
# terraform plan
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
data.oci_identity_availability_domains.ADs: Refreshing state...
data.oci_core_images.instance: Refreshing state...
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# oci_core_default_route_table.default-route-table1 will be created
+ resource "oci_core_default_route_table" "default-route-table1" {
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ manage_default_resource_id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ route_rules {
+ cidr_block = (known after apply)
+ destination = "0.0.0.0/0"
+ destination_type = "CIDR_BLOCK"
+ network_entity_id = (known after apply)
}
}
/*Omission*/
Plan: 32 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.
terraform apply
Terraform apply
applique les changements de configuration des ressources en fonction du plan d'exécution.
Lorsque cette commande est exécutée, un fichier terraform.tfstate sera généré.
# terraform apply
data.oci_identity_availability_domains.ADs: Refreshing state...
data.oci_core_images.instance: Refreshing state...
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# oci_core_default_route_table.default-route-table1 will be created
+ resource "oci_core_default_route_table" "default-route-table1" {
+ defined_tags = (known after apply)
+ display_name = (known after apply)
+ freeform_tags = (known after apply)
+ id = (known after apply)
+ manage_default_resource_id = (known after apply)
+ state = (known after apply)
+ time_created = (known after apply)
+ route_rules {
+ cidr_block = (known after apply)
+ destination = "0.0.0.0/0"
+ destination_type = "CIDR_BLOCK"
+ network_entity_id = (known after apply)
}
}
/*Omission*/
Plan: 32 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
oci_core_virtual_network.vcn2: Creating...
oci_core_virtual_network.vcn1: Creating...
/*Omission*/
Apply complete! Resources: 32 added, 0 changed, 0 destroyed.
Outputs:
lb_public_ip = [
[
{
"ip_address" = "X.X.X.X"
"is_public" = true
},
],
]
** Notes </ font> **
** Si vous avez des fichiers tf séparés pour chaque répertoire et que vous travaillez avec des compartiments différents, n'oubliez pas d'exécuter source env-vars
lorsque vous changez de répertoire. ** **
En tant que chapeau hiyari, j'ai travaillé dans l'environnement A. Ensuite, disons que vous allez dans le dict de l'environnement B et exécutez terraform apply
. Si les variables utilisées dans l'environnement A restent, il existe un risque de création ou de suppression de ressources dans des compartiments non souhaités.
Après avoir exécuté terraform apply
, accédez à l'écran de la console d'Oracle Cloud et vérifiez la ressource créée.
--Réseau cloud virtuel
Une fois cloud-init terminé, lorsque vous accédez à l'adresse IP de la sortie de l'équilibreur de charge par Outputs, «index.html» du serveur Web s'affiche.
terraform destroy
terraform destroy
supprime tout l'environnement construit.
# terraform destroy
data.oci_identity_availability_domains.ADs: Refreshing state...
/*Omission*/
Plan: 0 to add, 0 to change, 32 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
/*Omission*/
oci_core_virtual_network.vcn1: Destruction complete after 0s
Destroy complete! Resources: 32 destroyed.
Les images d'Oracle Cloud pouvant être utilisées avec Terraform sont les suivantes.
$ oci compute image list -c <OCID du compartiment>--all | jq -r '.data[] | ."operating-system"' | sort | uniq
Canonical Ubuntu
CentOS
Custom
Oracle Linux
Windows
Par conséquent, vous ne pouvez pas utiliser une image personnalisée telle que ** "Oracle Database". ** ** Si vous souhaitez démarrer un service de base de données dans Terraform, vous pouvez le faire en utilisant Managed Database Service-DBaaS.
Lors de la création de plusieurs instances, la quantité de code augmentera si vous écrivez pour chaque unité. L'exécution itérative peut être effectuée en utilisant un tableau de variables dans le fichier tf. Dans cet article, le nombre d'instances n'est pas important, nous définissons donc le nombre d'instances.
cloud-init Vous pouvez spécifier un script personnalisé pour la valeur de user_data dans le fichier tf. Voir Formats de données utilisateur pour savoir comment utiliser les données utilisateur.
Le fait d'utiliser cloud-init est qu'il ne vérifie pas le contenu du script personnalisé, donc même si terraform apply
réussit, le script peut échouer.
Par exemple, s'il y a un saut de ligne comme indiqué ci-dessous, il échouera.
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
De plus, même si «terraform apply» réussit, le processus Cloud-Init n'est pas encore terminé. Après vous être connecté à l'instance, vous pouvez vérifier si elle fonctionne comme prévu dans le fichier journal suivant.
# cat /var/log/cloud-init-output.log
Secondary VNIC Une attention particulière doit être prise lors de la configuration d'un VNIC secondaire dans Oracle Cloud. Dans cet article, nous exécutons secondary_vnic_all_configure.sh pour configurer l'adresse IP.
Par exemple, lors de l'exécution de terraform apply
, si le moment de l'appel de secondary_vnic_all_configure.sh est précoce, la configuration IP peut échouer. Par conséquent, dans cet article, le traitement du sommeil est inséré dans cloud-init.tpl spécifié dans userdata de cloud-Init et il est exécuté de manière fiable.
De plus, afin d'activer le VNIC secondaire lorsque le système d'exploitation est redémarré, cron est défini dans ʻinline de
remote-execdans le fichier tf. Si vous ne définissez pas d'adresse IP publique pour l'instance, vous ne pouvez pas utiliser
remote-exec`. Dans ce cas, cloud-init est un bon choix.
Après cela, lors de la séparation du réseau local d'entreprise et du réseau local de production comme dans cet article, il est recommandé de spécifier le réseau local d'opération en tant que VNIC principal.
Pour les ressources créées avant de déployer Terraform, vous pouvez également utiliser terraform import
pour coder l'environnement existant.
Terraform démontre sa vraie valeur dans chaque scène, de l'émission de l'environnement de vérification à la création de l'environnement de production et à la gestion de la configuration de la phase d'exploitation.
Pour ceux qui ont travaillé comme ingénieurs d'infrastructure dans un environnement hérité comme moi et qui ont grandi sur place, j'ai été très impressionné lorsque j'ai lancé pour la première fois «terraform apply» et créé les ressources.
De nos jours, les ingénieurs d'application développent également en utilisant Docker etc., mais je pense que Terraform est le rôle de SRE, qui se spécialise dans le domaine des infrastructures. Je pensais franchement que certaines choses ne pouvaient être prises en compte que par les personnes qui venaient à l'infrastructure.
Je souhaite continuer à utiliser Terraform pour créer un environnement où les développeurs peuvent se concentrer uniquement sur le développement.
Oracle Cloud/Terraform