Connecter des pods GKE aux bases de données Cloud SQL
Comment connecter facilement et en toute sécurité des pods exécutés dans Google Kubernetes Engine à une instance de base de données Google SQL gérée dans GCP. Nous utiliserons cloud-sql-proxy et workload identity pour le faire de la meilleure façon.
Table des matières
Création de l'instance de base de données SQL
Au moment de la rédaction de cet article, Google Cloud Platform prend en charge MySQL, PostgreSQL et SQL Server en tant que services de base de données SQL gérés. Utilisez votre outil préféré pour créer l'instance de base de données SQL et les autres ressources associées (utilisateurs, bases de données...).
Avec Terraform :
-
Pour créer l'instance de base de données SQL, nous pouvons utiliser la ressource Terraform : instance de base de données Google SQL.
-
Pour créer des utilisateurs de base de données, nous pouvons utiliser la ressource Terraform : utilisateur google sql . Si l'utilisateur créé est de type
BUILT_IN(celui par défaut) avec un nom d'utilisateur/mot de passe défini, il lui sera attribué le rôlecloudsqlsuperuserqui lui accorde la permission de lire/écrire dans toutes les bases de données et de créer d'autres utilisateurs. -
Pour créer une base de données à l'intérieur de l'instance de base de données SQL, nous pouvons utiliser la ressource Terraform : base de données Google SQL .
Nous souhaitons que le cluster GKE accède à l'instance de base de données SQL via une adresse IP privée. Pour y parvenir, nous devons procéder comme suit :
- Créez un réseau géré par Google SQL associé au VPC dans lequel réside le sous-réseau du cluster GKE
- Ce réseau Google SQL est géré par Google, donc les plages d'adresses IP privées sont choisies automatiquement
- Un lien de peering entre tous les sous-réseaux du VPC et le réseau géré pour les instances SQL sera automatiquement créé
- Lors de la création de l'instance de base de données SQL, nous devons spécifier un VPC. Le VPC à spécifier est celui déjà associé au réseau géré pour les instances de base de données Google SQL. De cette façon, tous les sous-réseaux à l'intérieur du VPC pourront communiquer de manière privée avec les bases de données SQL
Ce n'est pas très intuitif, je le sais, mais c'est comme ça que ça fonctionne. Le cluster GKE que nous utilisons doit être configuré comme un cluster VPC natif .
Créer un compte de service IAM
Le compte de service IAM que nous créons sera utilisé pour connecter nos pods à l'instance de base de données SQL via le proxy cloud-sql , grâce à workload identityUtilisez votre outil préféré pour créer le compte de service IAM.
Avec Terraform :
-
Nous pouvons utiliser la ressource Terraform : compte de service .
-
Nous devons alors accorder le rôle
cloudsql.clientau compte de service afin de permettre les connexions aux instances de base de données SQL. Nous pouvons utiliser la ressource Terraform : rôles/autorisations des comptes de service pour accorder les autorisations requises au compte de service.
Workload identity permettra au compte de service Kubernetes attaché à nos pods cloud-sql-proxy d'hériter des autorisations du compte de service IAM et donc de permettre aux pods cloud-sql-proxy de se connecter à l'instance de base de données SQL.
Notre conteneur d'application se connectera ensuite à l'instance de base de données SQL via le conteneur cloud-sql-proxy. En fait, nous aurons un pod avec deux conteneurs : un pour l'application, un pour cloud-sql-proxy.
Configuration de workload identity
Sans workload identity, nous devrons exporter la clé du compte de service IAM, créer un secret générique Kubernetes à partir de cette clé, rendre cette clé disponible sous forme de fichier dans nos pods cloud-sql-proxy, puis indiquer à cloud-sql-proxy d'utiliser ce fichier comme information d'identification lors de la tentative de connexion à l'instance de base de données SQL.
Avant de configurer workload identity, nous devons nous assurer que les conditions préalables suivantes sont remplies :
- Worload identity activé sur le cluster GKE. Peut s'effectuer avec :
- Workload identity activé sur les pools de nœuds GKE. Peut s'effectuer avec la CLI gcloud une fois workload identity activé sur le cluster :
--workload-metadata=GKE_METADATAlors de la création ou de la mise à jour du pool de nœuds. Commande complète ici- Une fois activé sur le cluster, workload identity sera automatiquement activé sur les pools de nœuds nouvellement créés, mais pas sur ceux déjà existants. Pour activer également workload identity sur les pools de nœuds plus anciens, voici la .
Nous allons maintenant configurer workload identity afin que notre compte de service GKE agisse en tant que le compte de service IAM. Pour cela, nous avons besoin des éléments suivants :
IAM_SA_ID: l'ID du compte de service IAM qui sera utilisé par notre compte de service GKE. Il sera sous la forme suivante :<service-account-name>@<gcp-project-id>.iam.gserviceaccount.com
GKE_SA_NAME: le nom du compte de service GKE qui agira en tant que compte de service IAM. Le compte de service GKE doit être annoté avec leIAM_SA_IDcomme indiqué ci-dessous:
annotations:
iam.gke.io/gcp-service-account: <IAM_SA_ID>
GKE_NAMESPACE: l'espace de noms GKE contenant nos ressources (pods d'application, compte de service...)PROJECT_ID: l'ID du projet GCP contenant nos ressources (le cluster GKE, le compte de service IAM...)
Une fois les éléments nécessaires correctement configurés, la liaison bidirectionnelle de workload identity entre le compte de service IAM et le compte de service GKE peut être activée avec la commande gcloud CLI suivante. Assurez-vous d'exporter les variables d'environnement requises avant d'exécuter la commande :
$ gcloud iam service-accounts add-iam-policy-binding $IAM_SA_ID \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:${PROJECT_ID}.svc.id.goog[${GKE_NAMESPACE}/${GKE_SA_NAME}]"
Après cela, notre compte de service GKE agira en tant que le compte de service IAM et héritera donc de ses autorisations. Les pods utilisant ce compte de service Kubernetes pourront effectuer les actions autorisées par les permissions du compte de service IAM.
Connexion des pods GKE à l'instance de base de données SQL
Nous devons d’abord nous assurer que l' API d'administration de Cloud SQL est activée sur notre projet GCP.
Une fois cela fait et workload identity correctement configuré, l'exemple de manifeste suivant pourrait être utilisé pour connecter nos conteneurs d'application à l'instance de base de données SQL via le proxy cloud-sql.
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
serviceAccountName: myapp # the Kubernetes service account inheriting
# the IAM service account disposing of the
# cloudsql.client role. That permission
# inheritance is possible thanks to the workload
# identity freature we configured.
containers:
- name: cloud-sql-proxy
# Available cloud-sql-proxy versions that
# can be used as the container image tag:
# https://github.com/GoogleCloudPlatform/cloud-sql-proxy/releases
image: gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.0.0
args:
- "--private-ip" # use the private IP of the SQL
# database instance to connect
- "--port=3306" # The port on which the proxy will listen on
# for connections that will be forwarded to the
# configured SQL database instance. The default
# listen host is 0.0.0.0 (all network interfaces)
- "<THE_SQL_DATABASE_INSTANCE_CONNECTION_NAME>"
securityContext:
runAsNonRoot: true
resources:
requests:
memory: "500Mi"
cpu: "0.6"
- name: myapp
image: myapp/myapp:0.0.1
ports:
- containerPort: 80
env:
- name: database_host
value: "127.0.0.1" # IP used to reach te SQL database instance
# through the cloud-sql-proxy container as the
# cloud-sql-proxy container is a sidecar container
# of the current pod
- name: database_port
value: "3306" # The port the cloud-sql-proxy is listening on
# for forwarding connections to the
# SQL database instance
- name: database_user
value: "myapp"
- name: database_name
value: "myapp"
- name: database_password
valueFrom:
secretKeyRef:
name: myapp-database
key: myapp_database_password
resources:
limits:
cpu: 0.5
memory: "500Mi"
requests:
cpu: 0.5
memory: "500Mi"